diff --git a/.gitignore b/.gitignore index 65b239a68ff..5dc058c97c0 100644 --- a/.gitignore +++ b/.gitignore @@ -205,6 +205,7 @@ configure-stamp *.bin *.mrk +*.mrk2 .dupload.conf diff --git a/.gitmodules b/.gitmodules index 1dc3af6dfad..567772bad60 100644 --- a/.gitmodules +++ b/.gitmodules @@ -67,6 +67,12 @@ [submodule "contrib/libgsasl"] path = contrib/libgsasl url = https://github.com/ClickHouse-Extras/libgsasl.git +[submodule "contrib/libcxx"] + path = contrib/libcxx + url = https://github.com/llvm-mirror/libcxx.git +[submodule "contrib/libcxxabi"] + path = contrib/libcxxabi + url = https://github.com/llvm-mirror/libcxxabi.git [submodule "contrib/snappy"] path = contrib/snappy url = https://github.com/google/snappy @@ -76,9 +82,15 @@ [submodule "contrib/brotli"] path = contrib/brotli url = https://github.com/google/brotli.git +[submodule "contrib/h3"] + path = contrib/h3 + url = https://github.com/uber/h3 [submodule "contrib/hyperscan"] path = contrib/hyperscan url = https://github.com/ClickHouse-Extras/hyperscan.git +[submodule "contrib/libunwind"] + path = contrib/libunwind + url = https://github.com/ClickHouse-Extras/libunwind.git [submodule "contrib/simdjson"] path = contrib/simdjson url = https://github.com/lemire/simdjson.git diff --git a/CHANGELOG.md b/CHANGELOG.md index bf86b2060e8..caf1f4fd7f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,69 @@ +## ClickHouse release 19.9.4.1, 2019-07-05 + +### Bug Fix +* Fix segfault in Delta codec which affects columns with values less than 32 bits size. The bug led to random memory corruption. [#5786](https://github.com/yandex/ClickHouse/pull/5786) ([alesapin](https://github.com/alesapin)) +* Fix rare bug in checking of part with LowCardinality column. [#5832](https://github.com/yandex/ClickHouse/pull/5832) ([alesapin](https://github.com/alesapin)) +* Fix segfault in TTL merge with non-physical columns in block. [#5819](https://github.com/yandex/ClickHouse/pull/5819) ([Anton Popov](https://github.com/CurtizJ)) +* Fix potential infinite sleeping of low-priority queries. [#5842](https://github.com/yandex/ClickHouse/pull/5842) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Fix how ClickHouse determines default time zone as UCT instead of UTC. [#5828](https://github.com/yandex/ClickHouse/pull/5828) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Fix bug about executing distributed DROP/ALTER/TRUNCATE/OPTIMIZE ON CLUSTER queries on follower replica before leader replica. Now they will be executed directly on leader replica. [#5757](https://github.com/yandex/ClickHouse/pull/5757) ([alesapin](https://github.com/alesapin)) +* Fix race condition, which cause that some queries may not appear in query_log instantly after SYSTEM FLUSH LOGS query. [#5685](https://github.com/yandex/ClickHouse/pull/5685) ([Anton Popov](https://github.com/CurtizJ)) +* Added missing support for constant arguments to `evalMLModel` function. [#5820](https://github.com/yandex/ClickHouse/pull/5820) ([alexey-milovidov](https://github.com/alexey-milovidov)) + +## ClickHouse release 19.7.6.1, 2019-07-05 + +### Bug Fix +* Fix performance regression in some queries with JOIN. [#5192](https://github.com/yandex/ClickHouse/pull/5192) ([Winter Zhang](https://github.com/zhang2014)) + +## ClickHouse release 19.9.2.4, 2019-06-24 + +### New Feature +* Print information about frozen parts in `system.parts` table. [#5471](https://github.com/yandex/ClickHouse/pull/5471) ([proller](https://github.com/proller)) +* Ask client password on clickhouse-client start on tty if not set in arguments [#5092](https://github.com/yandex/ClickHouse/pull/5092) ([proller](https://github.com/proller)) +* Implement `dictGet` and `dictGetOrDefault` functions for Decimal types. [#5394](https://github.com/yandex/ClickHouse/pull/5394) ([Artem Zuikov](https://github.com/4ertus2)) + +### Improvement +* Debian init: Add service stop timeout [#5522](https://github.com/yandex/ClickHouse/pull/5522) ([proller](https://github.com/proller)) +* Add setting forbidden by default to create table with suspicious types for LowCardinality [#5448](https://github.com/yandex/ClickHouse/pull/5448) ([Olga Khvostikova](https://github.com/stavrolia)) +* Regression functions return model weights when not used as State in function `evalMLMethod`. [#5411](https://github.com/yandex/ClickHouse/pull/5411) ([Quid37](https://github.com/Quid37)) +* Rename and improve regression methods. [#5492](https://github.com/yandex/ClickHouse/pull/5492) ([Quid37](https://github.com/Quid37)) +* Clearer interfaces of string searchers. [#5586](https://github.com/yandex/ClickHouse/pull/5586) ([Danila Kutenin](https://github.com/danlark1)) + +### Bug Fix +* Fix potential data loss in Kafka [#5445](https://github.com/yandex/ClickHouse/pull/5445) ([Ivan](https://github.com/abyss7)) +* Fix potential infinite loop in `PrettySpace` format when called with zero columns [#5560](https://github.com/yandex/ClickHouse/pull/5560) ([Olga Khvostikova](https://github.com/stavrolia)) +* Fixed UInt32 overflow bug in linear models. Allow eval ML model for non-const model argument. [#5516](https://github.com/yandex/ClickHouse/pull/5516) ([Nikolai Kochetov](https://github.com/KochetovNicolai)) +* `ALTER TABLE ... DROP INDEX IF EXISTS ...` should not raise an exception if provided index does not exist [#5524](https://github.com/yandex/ClickHouse/pull/5524) ([Gleb Novikov](https://github.com/NanoBjorn)) +* Fix segfault with `bitmapHasAny` in scalar subquery [#5528](https://github.com/yandex/ClickHouse/pull/5528) ([Zhichang Yu](https://github.com/yuzhichang)) +* Fixed error when replication connection pool doesn't retry to resolve host, even when DNS cache was dropped. [#5534](https://github.com/yandex/ClickHouse/pull/5534) ([alesapin](https://github.com/alesapin)) +* Fixed `ALTER ... MODIFY TTL` on ReplicatedMergeTree. [#5539](https://github.com/yandex/ClickHouse/pull/5539) ([Anton Popov](https://github.com/CurtizJ)) +* Fix INSERT into Distributed table with MATERIALIZED column [#5429](https://github.com/yandex/ClickHouse/pull/5429) ([Azat Khuzhin](https://github.com/azat)) +* Fix bad alloc when truncate Join storage [#5437](https://github.com/yandex/ClickHouse/pull/5437) ([TCeason](https://github.com/TCeason)) +* In recent versions of package tzdata some of files are symlinks now. The current mechanism for detecting default timezone gets broken and gives wrong names for some timezones. Now at least we force the timezone name to the contents of TZ if provided. [#5443](https://github.com/yandex/ClickHouse/pull/5443) ([Ivan](https://github.com/abyss7)) +* Fix some extremely rare cases with MultiVolnitsky searcher when the constant needles in sum are at least 16KB long. The algorithm missed or overwrote the previous results which can lead to the incorrect result of `multiSearchAny`. [#5588](https://github.com/yandex/ClickHouse/pull/5588) ([Danila Kutenin](https://github.com/danlark1)) +* Fix the issue when settings for ExternalData requests couldn't use ClickHouse settings. Also, for now, settings `date_time_input_format` and `low_cardinality_allow_in_native_format` cannot be used because of the ambiguity of names (in external data it can be interpreted as table format and in the query it can be a setting). [#5455](https://github.com/yandex/ClickHouse/pull/5455) ([Danila Kutenin](https://github.com/danlark1)) +* Fix bug when parts were removed only from FS without dropping them from Zookeeper. [#5520](https://github.com/yandex/ClickHouse/pull/5520) ([alesapin](https://github.com/alesapin)) +* Remove debug logging from MySQL protocol [#5478](https://github.com/yandex/ClickHouse/pull/5478) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Skip ZNONODE during DDL query processing [#5489](https://github.com/yandex/ClickHouse/pull/5489) ([Azat Khuzhin](https://github.com/azat)) +* Fix mix `UNION ALL` result column type. There were cases with inconsistent data and column types of resulting columns. [#5503](https://github.com/yandex/ClickHouse/pull/5503) ([Artem Zuikov](https://github.com/4ertus2)) +* Throw an exception on wrong integers in `dictGetT` functions instead of crash. [#5446](https://github.com/yandex/ClickHouse/pull/5446) ([Artem Zuikov](https://github.com/4ertus2)) +* Fix wrong element_count and load_factor for hashed dictionary in `system.dictionaries` table. [#5440](https://github.com/yandex/ClickHouse/pull/5440) ([Azat Khuzhin](https://github.com/azat)) + +### Build/Testing/Packaging Improvement +* Fixed build without `Brotli` HTTP compression support (`ENABLE_BROTLI=OFF` cmake variable). [#5521](https://github.com/yandex/ClickHouse/pull/5521) ([Anton Yuzhaninov](https://github.com/citrin)) +* Include roaring.h as roaring/roaring.h [#5523](https://github.com/yandex/ClickHouse/pull/5523) ([Orivej Desh](https://github.com/orivej)) +* Fix gcc9 warnings in hyperscan (#line directive is evil!) [#5546](https://github.com/yandex/ClickHouse/pull/5546) ([Danila Kutenin](https://github.com/danlark1)) +* Fix all warnings when compiling with gcc-9. Fix some contrib issues. Fix gcc9 ICE and submit it to bugzilla. [#5498](https://github.com/yandex/ClickHouse/pull/5498) ([Danila Kutenin](https://github.com/danlark1)) +* Fixed linking with lld [#5477](https://github.com/yandex/ClickHouse/pull/5477) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Remove unused specializations in dictionaries [#5452](https://github.com/yandex/ClickHouse/pull/5452) ([Artem Zuikov](https://github.com/4ertus2)) +* Improvement performance tests for formatting and parsing tables for different types of files [#5497](https://github.com/yandex/ClickHouse/pull/5497) ([Olga Khvostikova](https://github.com/stavrolia)) +* Fixes for parallel test run [#5506](https://github.com/yandex/ClickHouse/pull/5506) ([proller](https://github.com/proller)) +* Docker: use configs from clickhouse-test [#5531](https://github.com/yandex/ClickHouse/pull/5531) ([proller](https://github.com/proller)) +* Fix compile for FreeBSD [#5447](https://github.com/yandex/ClickHouse/pull/5447) ([proller](https://github.com/proller)) +* Upgrade boost to 1.70 [#5570](https://github.com/yandex/ClickHouse/pull/5570) ([proller](https://github.com/proller)) +* Fix build clickhouse as submodule [#5574](https://github.com/yandex/ClickHouse/pull/5574) ([proller](https://github.com/proller)) +* Improve JSONExtract performance tests [#5444](https://github.com/yandex/ClickHouse/pull/5444) ([Vitaly Baranov](https://github.com/vitlibar)) + ## ClickHouse release 19.8.3.8, 2019-06-11 ### New Features diff --git a/CHANGELOG_RU.md b/CHANGELOG_RU.md index c77ca600946..2fa1f34ce04 100644 --- a/CHANGELOG_RU.md +++ b/CHANGELOG_RU.md @@ -1,3 +1,119 @@ +## ClickHouse release 19.9.4.1, 2019-07-05 + +### Исправления ошибок +* Исправлен segmentation fault в кодеке сжатия Delta в колонках с величинами размером меньше 32 бит. Ошибка могла приводить к повреждениям памяти. [#5786](https://github.com/yandex/ClickHouse/pull/5786) ([alesapin](https://github.com/alesapin)) +* Исправлена ошибка в проверке кусков в LowCardinality колонках. [#5832](https://github.com/yandex/ClickHouse/pull/5832) ([alesapin](https://github.com/alesapin)) +* Исправлен segmentation fault при слиянии кусков с истекшим TTL в случае, когда в блоке присутствуют столбцы, не входящие в структуру таблицы. [#5819](https://github.com/yandex/ClickHouse/pull/5819) ([Anton Popov](https://github.com/CurtizJ)) +* Исправлена существовавшая возможность ухода в бесконечное ожидание на низко-приоритетных запросах. [#5842](https://github.com/yandex/ClickHouse/pull/5842) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Исправлена ошибка определения таймзоны по умолчанию (UCT вместо UTC). [#5828](https://github.com/yandex/ClickHouse/pull/5828) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Исправлена ошибка в распределенных запросах вида DROP/ALTER/TRUNCATE/OPTIMIZE ON CLUSTER. [#5757](https://github.com/yandex/ClickHouse/pull/5757) ([alesapin](https://github.com/alesapin)) +* Исправлена ошибка, которая при распределенных запросах могла привести к тому, что некоторые запросы не появлялись в query_log сразу после SYSTEM FLUSH LOGS запроса. [#5685](https://github.com/yandex/ClickHouse/pull/5685) ([Anton Popov](https://github.com/CurtizJ)) +* Добавлена отсутствовавшая поддержка константных аргументов для функции `evalMLModel`. [#5820](https://github.com/yandex/ClickHouse/pull/5820) ([alexey-milovidov](https://github.com/alexey-milovidov)) + +## ClickHouse release 19.7.6.1, 2019-07-05 + +### Исправления ошибок +* Исправлена просадка производительности в методе JOIN в некоторых видах запросов. [#5192](https://github.com/yandex/ClickHouse/pull/5192) ([Winter Zhang](https://github.com/zhang2014)) + +## ClickHouse release 19.8.3.8, 2019-06-11 + +### Новые возможности +* Добавлены функции для работы с JSON. [#4686](https://github.com/yandex/ClickHouse/pull/4686) ([hcz](https://github.com/hczhcz)) [#5124](https://github.com/yandex/ClickHouse/pull/5124). ([Vitaly Baranov](https://github.com/vitlibar)) +* Добавлена функция `basename`, аналогичная функции `basename` в различных языках программирования (`os.path.basename` в python, `basename` в PHP, и т.д.). Работает с UNIX и Windows подобными путями. [#5136](https://github.com/yandex/ClickHouse/pull/5136) ([Guillaume Tassery](https://github.com/YiuRULE)) +* Добавлена возможность указать смещение в секции LIMIT BY с помощью синтаксиса `LIMIT n, m BY` или `LIMIT m OFFSET n BY`. [#5138](https://github.com/yandex/ClickHouse/pull/5138) ([Anton Popov](https://github.com/CurtizJ)) +* Добавлен новый тип данных `SimpleAggregateFunction`, который позволяет создавать столбцы с легковесной агрегацией в AggregatingMergeTree. Он может использоваться только с простыми функциями, такими как `any`,` anyLast`, `sum`,` min`, `max`. + [#4629](https://github.com/yandex/ClickHouse/pull/4629) ([Boris Granveaud](https://github.com/bgranvea)) +* Добавлена поддержка неконстантных аргументов в функции `ngramDistance` [#5198](https://github.com/yandex/ClickHouse/pull/5198) ([Danila Kutenin](https://github.com/danlark1)) +* Добавлены функции `skewPop`, `skewSamp`, `kurtPop` и `kurtSamp`, которые вычисляют для последовательности коэффициент асимметрии, выборочный коэффициент асимметрии, коэффициент эксцесса и выборочный коэффициент эксцесса соответсвенно. [#5200](https://github.com/yandex/ClickHouse/pull/5200) ([hcz](https://github.com/hczhcz)) +* Добавлена поддержка операции `RENAME` для движка `MaterializedView`. [#5209](https://github.com/yandex/ClickHouse/pull/5209) ([Guillaume Tassery](https://github.com/YiuRULE)) +* Сервер, позволяющий подключаться к ClickHouse через клиент MySQL. [#4715](https://github.com/yandex/ClickHouse/pull/4715) ([Yuriy Baranov](https://github.com/yurriy)) +* Добавлены функции `toDecimal*OrZero` и `toDecimal*OrNull`. [#5291](https://github.com/yandex/ClickHouse/pull/5291) ([Artem Zuikov](https://github.com/4ertus2)) +* Добавлена поддержка Decimal в функциях: `quantile`, `quantiles`, `median`, `quantileExactWeighted`, `quantilesExactWeighted`, `medianExactWeighted`. [#5304](https://github.com/yandex/ClickHouse/pull/5304) ([Artem Zuikov](https://github.com/4ertus2)) +* Добавлена функция `toValidUTF8`, которая заменяет все некорректные символы в кодировке UTF-8 на заменяющий символ � (U+FFFD). [#5322](https://github.com/yandex/ClickHouse/pull/5322) ([Danila Kutenin](https://github.com/danlark1)) +* Добавлена функция `format`, которая выполняет подстановку в константный шаблон (упрощенный шаблон форматирования, используемый в Python) строк, переданных в аргументах функции. [#5330](https://github.com/yandex/ClickHouse/pull/5330) ([Danila Kutenin](https://github.com/danlark1)) +* Добавлена системная таблица `system.detached_parts`, содержащая информацию о кусках из директории `detached` для таблиц семейства `MergeTree`. [#5353](https://github.com/yandex/ClickHouse/pull/5353) ([akuzm](https://github.com/akuzm)) +* Добавлена функция `ngramSearch` для вычисления несимметричной разности между `needle` и `haystack`. [#5418](https://github.com/yandex/ClickHouse/pull/5418)[#5422](https://github.com/yandex/ClickHouse/pull/5422) ([Danila Kutenin](https://github.com/danlark1)) +* Реализованы основные методы машинного обучения (стохастическая линейная регрессия и логистическая регрессия) в виде агрегатных функций. Для вычисления весов могут использоваться различные методы (градиентный спуск, градиентный спуск с накоплением импульса, метод Нестерова). Также поддерживаются mini-batches произвольного размера. [#4943](https://github.com/yandex/ClickHouse/pull/4943) ([Quid37](https://github.com/Quid37)) +* Добавлены функции `geohashEncode` и `geohashDecode`. [#5003](https://github.com/yandex/ClickHouse/pull/5003) ([Vasily Nemkov](https://github.com/Enmk)) +* Добавлена агрегатная функция `timeSeriesGroupSum`, которая агрегирует временные ряды в которых не совпадают моменты. Функция использует линейную интерполяцию между двумя значениями времени, а затем суммирует значения для одного и того же момента. Добавлена агрегатная функция `timeSeriesGroupRateSum`, которая вычисляет производные по timestamp для рядов, а затем суммирует полученные производные для всех рядов для одного значения timestamp. [#4542](https://github.com/yandex/ClickHouse/pull/4542) ([Yangkuan Liu](https://github.com/LiuYangkuan)) +* Добавлены функции `IPv4CIDRtoIPv4Range` and `IPv6CIDRtoIPv6Range`, которые вычисляют диапазон подсети, используя CIDR. [#5095](https://github.com/yandex/ClickHouse/pull/5095) ([Guillaume Tassery](https://github.com/YiuRULE)) +* Добавлен заголовок X-ClickHouse-Summary при отправке HTTP запроса с включенной настройкой `send_progress_in_http_headers`. Он содержит инфорцию о X-ClickHouse-Progress, а также информацию о том сколько строк и байт было записано в таблицу и подобное. [#5116](https://github.com/yandex/ClickHouse/pull/5116) ([Guillaume Tassery](https://github.com/YiuRULE)) + +### Улучшения +* Добавлена настройка `max_parts_in_total` (по умолчанию: 100 000) для таблиц семейства MergeTree, предотвращающая неправильное задание ключа партиционирования #5166. [#5171](https://github.com/yandex/ClickHouse/pull/5171) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* `clickhouse-obfuscator`: теперь seed вычисляется для столбцов путем комбинирования начального seed и имени колонки, а не ее позиции. Это необходимо для того, чтобы оставить таблицы пригодными для JOIN-ов при преобразовании датасетов с несколькими таблицами. [#5178](https://github.com/yandex/ClickHouse/pull/5178) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Добавлены функции `JSONExtractRaw`, `JSONExtractKeyAndValues`. Функции вида `jsonExtract` переименованы в `JSONExtract`. Теперь, в случае ошибки эти функции возвращают соответсвующие типу значения, а не `NULL`. Теперь возвращаемый тип передается в функцию `JSONExtract` последним параметром. Если недоступны иструкции AVX2, то JSON функции выполняются с использованием бибилиотеки RapidJSON. Обновлена библиотека Simdjson. [#5235](https://github.com/yandex/ClickHouse/pull/5235) ([Vitaly Baranov](https://github.com/vitlibar)) +* Теперь функции `if` and `multiIf` не зависят от условных `Nullable` типов. [#5238](https://github.com/yandex/ClickHouse/pull/5238) ([Jian Wu](https://github.com/janplus)) +* Оператор `IN` теперь возвращает `Null` для значений равных `Null` (аналогично функции `Equal`). [#5152](https://github.com/yandex/ClickHouse/pull/5152) ([Jian Wu](https://github.com/janplus)) +* Добавлена проверка ограничения по времени выполенения запроса через каждые (flush_interval / poll_timeout) строк при чтении из движка Kafka. Это позволяет чаще прерывать чтение из движка Kafka и чаще проверять ограничение по времени на более высоком уровне конвеера выполнения запроса. [#5249](https://github.com/yandex/ClickHouse/pull/5249) ([Ivan](https://github.com/abyss7)) +* Теперь библиотека rdkafka линкуется c bundled библиотекой SASL. Это позволяет использовать SASL SCRAM аутентификацию. [#5253](https://github.com/yandex/ClickHouse/pull/5253) ([Ivan](https://github.com/abyss7)) +* clickhouse-server: более информативные сообщения об ошибках прослушивания. [#5268](https://github.com/yandex/ClickHouse/pull/5268) ([proller](https://github.com/proller)) +* clickhouse-copier: добавлена поддержка словарей в функциях в секции ``. [#5270](https://github.com/yandex/ClickHouse/pull/5270) ([proller](https://github.com/proller)) +* Добавлена настройка `kafka_commit_every_batch` для регулирования чтения данных из движка Kafka. Позволяет установить вид чтения: после каждого полученного пакета сообщений или после того как блок записан в таблицу. [#5308](https://github.com/yandex/ClickHouse/pull/5308) ([Ivan](https://github.com/abyss7)) +* Добавлена поддержка беззнаковых целых типов отличных от UInt32 в функциях `windowFunnel`, `sequenceMatch`. [#5339](https://github.com/yandex/ClickHouse/pull/5339) [#5320](https://github.com/yandex/ClickHouse/pull/5320) ([sundyli](https://github.com/sundy-li)) +* В движке Merge виртуальный столбец с названием `_table` (содержащий название таблицы) теперь недоступен, если он присутствует в таблицах-источниках. [#5325](https://github.com/yandex/ClickHouse/pull/5325) ([Ivan](https://github.com/abyss7)) +* Более понятные сообщения об ошибках, если чексуммы не совпадают вероятнее всего из-за ошибок на аппаратном уровне. [#5355](https://github.com/yandex/ClickHouse/pull/5355) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Для движка `Merge` добавлена проверка на то, что таблицы-источники поддерживают семплирование. [#5366](https://github.com/yandex/ClickHouse/pull/5366) ([Ivan](https://github.com/abyss7)) +* Теперь после использования MySQL в качестве внешнего словаря закрывается соединение. [#5395](https://github.com/yandex/ClickHouse/pull/5395) ([Clément Rodriguez](https://github.com/clemrodriguez)) +* Улучшения в протоколе MySQL Wire. Формат переименован из `MySQL` to `MySQLWire`. Теперь SSL недоступно, если не удалось создать SSL контекст. [#5419](https://github.com/yandex/ClickHouse/pull/5419) ([Yuriy Baranov](https://github.com/yurriy)) +* clickhouse-client: теперь можно запустить клиент, если файл истории недоступен. [#5431](https://github.com/yandex/ClickHouse/pull/5431) ([proller](https://github.com/proller)) +* Теперь учитываются настройки запроса при асинхронных вставках в таблицу типа Distributed. [#4936](https://github.com/yandex/ClickHouse/pull/4936) ([TCeason](https://github.com/TCeason)) +* Переименованы функции `leastSqr` в `simpleLinearRegression`, `LinearRegression` в `linearRegression`, `LogisticRegression` в `logisticRegression`. [#5391](https://github.com/yandex/ClickHouse/pull/5391) ([Nikolai Kochetov](https://github.com/KochetovNicolai)) + +### Улучшения производительности +* Паралелльная обработка кусков в запросах `ALTER ... MODIFY`. [#4639](https://github.com/yandex/ClickHouse/pull/4639) ([Ivan Kush](https://github.com/IvanKush)) +* Оптимизации в обработке регулярных выражений. [#5193](https://github.com/yandex/ClickHouse/pull/5193) [#5191](https://github.com/yandex/ClickHouse/pull/5191) ([Danila Kutenin](https://github.com/danlark1)) +* Теперь столбец правой таблицы, который используется только в секции `JOIN ON` не добавляется в результат. [#5260](https://github.com/yandex/ClickHouse/pull/5260) ([Artem Zuikov](https://github.com/4ertus2)) +* Теперь чтение из буфера движка Kafka приостанавливается после первого пустого ответа. Это позволяет не вызывать несколько раз метод `ReadBuffer::next()` для пустого результата. [#5283](https://github.com/yandex/ClickHouse/pull/5283) ([Ivan](https://github.com/abyss7)) +* Оптимизация функции `concat` для нескольких аргументов. [#5357](https://github.com/yandex/ClickHouse/pull/5357) ([Danila Kutenin](https://github.com/danlark1)) +* Оптимизация запросов. Прокидывание выражения оператора `IN` при конвертации `commа/cross join` в `inner`. [#5396](https://github.com/yandex/ClickHouse/pull/5396) ([Artem Zuikov](https://github.com/4ertus2)) +* Улучшение реализации LZ4 для более быстрого разжатия данных. [#5070](https://github.com/yandex/ClickHouse/pull/5070) ([Danila Kutenin](https://github.com/danlark1)) +* Реализована MSD-сортировка, а также на ее основе частичная сортировка. [#5129](https://github.com/yandex/ClickHouse/pull/5129) ([Evgenii Pravda](https://github.com/kvinty)) + +### Исправления ошибок +* Исправлено прокидывание необходимых для чтения столбцов в join. [#5192](https://github.com/yandex/ClickHouse/pull/5192) ([Winter Zhang](https://github.com/zhang2014)) +* Исправлено неправильное поведение команды `sudo service clickhouse-server forcerestart` в случае, если сервер запущен при помощи systemd. [#5204](https://github.com/yandex/ClickHouse/pull/5204) ([proller](https://github.com/proller)) +* Исправлены коды ошибок при передаче кусков (раньше даже при ошибках возвращался код 200). [#5216](https://github.com/yandex/ClickHouse/pull/5216) ([proller](https://github.com/proller)) +* Исправлено использование типа SimpleAggregateFunction со строками длиннее чем `MAX_SMALL_STRING_SIZE` [#5311](https://github.com/yandex/ClickHouse/pull/5311) ([Azat Khuzhin](https://github.com/azat)) +* Исправлена ошибка конвертации типа `Decimal` в `Nullable(Decimal)` в секции IN. Добавлена возможность конвертации между различными типами Decimal (including different scales). [#5350](https://github.com/yandex/ClickHouse/pull/5350) ([Artem Zuikov](https://github.com/4ertus2)) +* Исправлено затирание регистров FPU в библиотеке simdjson, которое приводило к неправильным вычислениям в агрегатных функциях `uniqHLL` и `uniqCombined`, а также математических функциях, таких как `log`. [#5354](https://github.com/yandex/ClickHouse/pull/5354) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Исправлены обработка константных и неконстантных аргументов одновременно в JSON функциях. [#5435](https://github.com/yandex/ClickHouse/pull/5435) ([Vitaly Baranov](https://github.com/vitlibar)) +* Исправлен возвращаемый тип в функции `quantileExact` с типом `Decimal`. [#5304](https://github.com/yandex/ClickHouse/pull/5304) ([Artem Zuikov](https://github.com/4ertus2)) + +### Улучшения сборки, тестирования и пакетирования +* Исправлены срабатывания address-санитайзера, показывающие потенциальную ошибку use-after-free.[#5139](https://github.com/yandex/ClickHouse/pull/5139) [#5143](https://github.com/yandex/ClickHouse/pull/5143) [#5393](https://github.com/yandex/ClickHouse/pull/5393) ([Ivan](https://github.com/abyss7)) +* Тесты производительности перемещены в одну директорию. [#5158](https://github.com/yandex/ClickHouse/pull/5158) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Исправлены некоторые тесты производительности. [#5255](https://github.com/yandex/ClickHouse/pull/5255) ([alesapin](https://github.com/alesapin)) +* Добавлена утилита, позволяющая вычислять чексуммы, полученные в результате возможных инверсий битов. Она помогает отлаживать аппаратные ошибки. [#5334](https://github.com/yandex/ClickHouse/pull/5334) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Улучшение скрипта для запуска интеграционных тестов. [#5340](https://github.com/yandex/ClickHouse/pull/5340)[#5360](https://github.com/yandex/ClickHouse/pull/5360) ([filimonov](https://github.com/filimonov)) +* Добавлена инструкция о том, как писать тесты производительности. [#5408](https://github.com/yandex/ClickHouse/pull/5408) ([alesapin](https://github.com/alesapin)) +* Добавлена возможность делать подстановки в запросах create, fill и drop в тестах производительности. [#5367](https://github.com/yandex/ClickHouse/pull/5367) ([Olga Khvostikova](https://github.com/stavrolia)) + +## ClickHouse release 19.7.5.27, 2019-06-09 + +### Новые возможности +* Добавлены функции для битмапов `bitmapHasAny` и `bitmapHasAll` (аналогично функциям `hasAny` и `hasAll` для массивов). [#5279](https://github.com/yandex/ClickHouse/pull/5279) ([Sergi Vladykin](https://github.com/svladykin)) + +### Исправления ошибок +* Исправлен segfault при использовании `minmax` индекса со значениями `Null`. [#5246](https://github.com/yandex/ClickHouse/pull/5246) ([Nikita Vasilev](https://github.com/nikvas0)) +* Исправлена ошибка 'Not found column', возникавшая в некоторых распределенных запросах. [#5407](https://github.com/yandex/ClickHouse/pull/5407) ([Constantin S. Pan](https://github.com/kvap)) +* Исправлена ошибка "Column '0' already exists" в запросах `SELECT .. PREWHERE` со столбцами с указанным `DEFAULT` [#5397](https://github.com/yandex/ClickHouse/pull/5397) ([proller](https://github.com/proller)) +* Исправлен запрос `ALTER MODIFY TTL` для таблиц типа `ReplicatedMergeTree`. [#5539](https://github.com/yandex/ClickHouse/pull/5539/commits) ([Anton Popov](https://github.com/CurtizJ)) +* Теперь сервер не падает, если подписчики Kafka не смогли запуститься. [#5285](https://github.com/yandex/ClickHouse/pull/5285) ([Ivan](https://github.com/abyss7)) +* Исправлены bitmap функции. [#5359](https://github.com/yandex/ClickHouse/pull/5359) ([Andy Yang](https://github.com/andyyzh)) +* Исправлено значение `element_count` в таблице `system.dictionaries` для словарей типа hashed (теперь не подсчитываются дубликаты). [#5440](https://github.com/yandex/ClickHouse/pull/5440) ([Azat Khuzhin](https://github.com/azat)) +* Для определения имени таймзоны теперь используется переменная среды TZ. В некоторых случаях это помогает правильно определять таймзону по умолчанию. [#5443](https://github.com/yandex/ClickHouse/pull/5443) ([Ivan](https://github.com/abyss7)) +* Убрано неявное преобразование целых типов в функциях `dictGetT`, т.к. оно работало неправильно. Вместо этого теперь бросается исключение. [#5446](https://github.com/yandex/ClickHouse/pull/5446) ([Artem Zuikov](https://github.com/4ertus2)) +* Исправлены настройки во внешних данных HTTP запроса. [#5455](https://github.com/yandex/ClickHouse/pull/5455) ([Danila Kutenin](https://github.com/danlark1)) +* Исправлена ошибка, приводящая к тому, что куски удалялись только из файловой системы, но не из Zookeeper. [#5520](https://github.com/yandex/ClickHouse/pull/5520) ([alesapin](https://github.com/alesapin)) +* Исправлен segfault в функции `bitmapHasAny`. [#5528](https://github.com/yandex/ClickHouse/pull/5528) ([Zhichang Yu](https://github.com/yuzhichang)) +* Исправлена ошибка, приводящая к тому, что при репликации не вычислялся заново адрес хоста, даже если DNS кеш был сброшен. [#5534](https://github.com/yandex/ClickHouse/pull/5534) ([alesapin](https://github.com/alesapin)) +* Исправлен запрос `DROP INDEX IF EXISTS`. Теперь запрос `ALTER TABLE ... DROP INDEX IF EXISTS ...` не выкидывает исключение. [#5524](https://github.com/yandex/ClickHouse/pull/5524) ([Gleb Novikov](https://github.com/NanoBjorn)) +* Исправлен тип результируещего столбца в запросе `UNION ALL`. Раньше могли быть случаи, когда тип и данные столбца были несогласованы. [#5503](https://github.com/yandex/ClickHouse/pull/5503) ([Artem Zuikov](https://github.com/4ertus2)) +* Исправлена ошибка, вследствие которой поток `DDLWorker`-а мог быть остановлен, если одна нода удалила `znode` из очереди задач, а другая уже получила ее, но не успела выполнить. [#5489](https://github.com/yandex/ClickHouse/pull/5489) ([Azat Khuzhin](https://github.com/azat)) +* Исправлена вставка в Distributed таблицы с материализованныси столбцами. [#5429](https://github.com/yandex/ClickHouse/pull/5429) ([Azat Khuzhin](https://github.com/azat)) + + ## ClickHouse release 19.7.3.9, 2019-05-30 ### Новые возможности @@ -63,6 +179,17 @@ Kutenin](https://github.com/danlark1)) ([proller](https://github.com/proller)) +## ClickHouse release 19.6.3.18, 2019-06-13 + +### Исправления ошибок +* Исправлено прокидывание условий оператора IN для запросов с табличными функциями `mysql` and `odbc` и соответсвующими движками таблиц. [#5313](https://github.com/yandex/ClickHouse/pull/5313) ([alexey-milovidov](https://github.com/alexey-milovidov)) +* Исправлен deadlock в Zookeeper. [#5297](https://github.com/yandex/ClickHouse/pull/5297) ([github1youlc](https://github.com/github1youlc)) +* Для формата CSV добавлена возможность указывать значения типа Decimal в кавычках. [#5284](https://github.com/yandex/ClickHouse/pull/5284) ([Artem Zuikov](https://github.com/4ertus2) +* Убрана возможность преобразований из float Inf/NaN в Decimal (теперь бросается исключение). [#5282](https://github.com/yandex/ClickHouse/pull/5282) ([Artem Zuikov](https://github.com/4ertus2)) +* Исправлен data race в запросе `RENAME`. [#5247](https://github.com/yandex/ClickHouse/pull/5247) ([Winter Zhang](https://github.com/zhang2014)) +* Отключен LFAlloc. Использование LFAlloc могло приводить к ошибкам MAP_FAILED при использовании UncompressedCache и в результате к падению запросов на высоконагруженных серверах. [cfdba93](https://github.com/yandex/ClickHouse/commit/cfdba938ce22f16efeec504f7f90206a515b1280)([Danila Kutenin](https://github.com/danlark1)) + + ## ClickHouse release 19.6.2.11, 2019-05-13 ### Новые возможности diff --git a/CMakeLists.txt b/CMakeLists.txt index 283e19247af..6262d17f2d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,13 +38,13 @@ if (COMPILER_GCC) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7 AND NOT CMAKE_VERSION VERSION_LESS 2.8.9) message (FATAL_ERROR "GCC version must be at least 7. For example, if GCC 7 is available under gcc-7, g++-7 names, do the following: export CC=gcc-7 CXX=g++-7; rm -rf CMakeCache.txt CMakeFiles; and re run cmake or ./release.") endif () -elseif (COMPILER_CLANG) - # Require at least clang 5 - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5) - message (FATAL_ERROR "Clang version must be at least 5.") +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # Require at least clang 6 + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6) + message (FATAL_ERROR "Clang version must be at least 6.") endif () else () - message (WARNING "You are using an unsupported compiler. Compilation has only been tested with Clang 5+ and GCC 7+.") + message (WARNING "You are using an unsupported compiler. Compilation has only been tested with Clang 6+ and GCC 7+.") endif () # Check that submodules are present only if source was downloaded with git @@ -104,7 +104,6 @@ if (COMPILER_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "8.3.0") endif () if (COMPILER_CLANG) - # clang: warning: argument unused during compilation: '-stdlib=libc++' # clang: warning: argument unused during compilation: '-specs=/usr/share/dpkg/no-pie-compile.specs' [-Wunused-command-line-argument] set (COMMON_WARNING_FLAGS "${COMMON_WARNING_FLAGS} -Wno-unused-command-line-argument") endif () @@ -117,10 +116,16 @@ if (CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64") if (OS_LINUX AND NOT UNBUNDLED AND MAKE_STATIC_LIBRARIES AND NOT SPLIT_SHARED_LIBRARIES AND CMAKE_VERSION VERSION_GREATER "3.9.0") option (GLIBC_COMPATIBILITY "Set to TRUE to enable compatibility with older glibc libraries. Only for x86_64, Linux. Implies USE_INTERNAL_MEMCPY." ON) endif () + + if (NOT CMAKE_VERSION VERSION_GREATER "3.9.0") + message (WARNING "CMake version must be greater than 3.9.0 for production builds.") + endif () endif () if (GLIBC_COMPATIBILITY) set (USE_INTERNAL_MEMCPY ON) +else () + message (WARNING "Option GLIBC_COMPATIBILITY must be turned on for production builds.") endif () string(REGEX MATCH "-?[0-9]+(.[0-9]+)?$" COMPILER_POSTFIX ${CMAKE_CXX_COMPILER}) @@ -183,6 +188,7 @@ if(WITH_COVERAGE AND COMPILER_CLANG) endif() if(WITH_COVERAGE AND COMPILER_GCC) set(COMPILER_FLAGS "${COMPILER_FLAGS} -fprofile-arcs -ftest-coverage") + set(COVERAGE_OPTION "-lgcov") endif() set (CMAKE_BUILD_COLOR_MAKEFILE ON) @@ -196,13 +202,75 @@ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMPILER_FLAGS} -fn set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 ${CMAKE_C_FLAGS_ADD}") set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g3 -ggdb3 -fno-inline ${CMAKE_C_FLAGS_ADD}") -include (cmake/use_libcxx.cmake) +# Uses MAKE_STATIC_LIBRARIES + + +option (UNBUNDLED "Try find all libraries in system. We recommend to avoid this mode for production builds, because we cannot guarantee exact versions and variants of libraries your system has installed. This mode exists for enthusiastic developers who search for trouble. Also it is useful for maintainers of OS packages." OFF) +if (UNBUNDLED) + set(NOT_UNBUNDLED 0) +else () + set(NOT_UNBUNDLED 1) +endif () +# Using system libs can cause lot of warnings in includes. +if (UNBUNDLED OR NOT (OS_LINUX OR APPLE) OR ARCH_32) + option (NO_WERROR "Disable -Werror compiler option" ON) +endif () + + +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package (Threads) + +include (cmake/find_cxxabi.cmake) +include (cmake/find_cxx.cmake) + +include (cmake/test_compiler.cmake) + +if (OS_LINUX AND COMPILER_CLANG AND USE_STATIC_LIBRARIES) + option (USE_LIBCXX "Use libc++ and libc++abi instead of libstdc++ (only make sense on Linux)" ${HAVE_LIBCXX}) + + if (USE_LIBCXX) + set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_LIBCPP_DEBUG=0") # More checks in debug build. + endif () +endif () + +if (USE_LIBCXX) + set (STATIC_STDLIB_FLAGS "") +else () + set (STATIC_STDLIB_FLAGS "-static-libgcc -static-libstdc++") +endif () + +if (MAKE_STATIC_LIBRARIES AND NOT APPLE AND NOT (COMPILER_CLANG AND OS_FREEBSD)) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${STATIC_STDLIB_FLAGS}") + + # Along with executables, we also build example of shared library for "library dictionary source"; and it also should be self-contained. + set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${STATIC_STDLIB_FLAGS}") +endif () + +if (USE_STATIC_LIBRARIES AND HAVE_NO_PIE) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG_NO_PIE}") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAG_NO_PIE}") +endif () + +if (NOT SANITIZE) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined") + set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") +endif() + +include (cmake/find_unwind.cmake) + +if (USE_INTERNAL_UNWIND_LIBRARY) + option (USE_INTERNAL_UNWIND_LIBRARY_FOR_EXCEPTION_HANDLING "Use internal unwind library for exception handling" ${USE_STATIC_LIBRARIES}) +endif () + # Set standard, system and compiler libraries explicitly. # This is intended for more control of what we are linking. +string (TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UC) +set (CMAKE_POSTFIX_VARIABLE "CMAKE_${CMAKE_BUILD_TYPE_UC}_POSTFIX") + set (DEFAULT_LIBS "") -if (OS_LINUX AND NOT UNBUNDLED AND (GLIBC_COMPATIBILITY OR USE_LIBCXX)) +if (OS_LINUX AND NOT UNBUNDLED AND (GLIBC_COMPATIBILITY OR USE_INTERNAL_UNWIND_LIBRARY_FOR_EXCEPTION_HANDLING OR USE_LIBCXX)) # Note: this probably has no effect, but I'm not an expert in CMake. set (CMAKE_C_IMPLICIT_LINK_LIBRARIES "") set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") @@ -214,8 +282,13 @@ if (OS_LINUX AND NOT UNBUNDLED AND (GLIBC_COMPATIBILITY OR USE_LIBCXX)) set (BUILTINS_LIB_PATH "") if (COMPILER_CLANG) execute_process (COMMAND ${CMAKE_CXX_COMPILER} --print-file-name=libclang_rt.builtins-${CMAKE_SYSTEM_PROCESSOR}.a OUTPUT_VARIABLE BUILTINS_LIB_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) + else () + set (BUILTINS_LIB_PATH "-lgcc") endif () + string (TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UC) + set (CMAKE_POSTFIX_VARIABLE "CMAKE_${CMAKE_BUILD_TYPE_UC}_POSTFIX") + # Add C++ libraries. # # This consist of: @@ -225,10 +298,26 @@ if (OS_LINUX AND NOT UNBUNDLED AND (GLIBC_COMPATIBILITY OR USE_LIBCXX)) # - compiler builtins (example: functions for implementation of __int128 operations); # # There are two variants of C++ library: libc++ (from LLVM compiler infrastructure) and libstdc++ (from GCC). - if (USE_LIBCXX) - set (DEFAULT_LIBS "${DEFAULT_LIBS} -Wl,-Bstatic -lc++ -lc++abi -lgcc_eh ${BUILTINS_LIB_PATH} -Wl,-Bdynamic") + + if (USE_INTERNAL_UNWIND_LIBRARY_FOR_EXCEPTION_HANDLING) + # TODO: Allow to use non-static library as well. + set (EXCEPTION_HANDLING_LIBRARY "${ClickHouse_BINARY_DIR}/contrib/libunwind-cmake/libunwind_static${${CMAKE_POSTFIX_VARIABLE}}.a") else () - set (DEFAULT_LIBS "${DEFAULT_LIBS} -Wl,-Bstatic -lstdc++ -lgcc_eh -lgcc ${BUILTINS_LIB_PATH} -Wl,-Bdynamic") + set (EXCEPTION_HANDLING_LIBRARY "-lgcc_eh") + endif () + + message (STATUS "Using exception handling library: ${EXCEPTION_HANDLING_LIBRARY}") + + if (USE_LIBCXX) + if (USE_INTERNAL_LIBCXX_LIBRARY) + set (LIBCXX_LIBS "${ClickHouse_BINARY_DIR}/contrib/libcxx-cmake/libcxx_static${${CMAKE_POSTFIX_VARIABLE}}.a ${ClickHouse_BINARY_DIR}/contrib/libcxxabi-cmake/libcxxabi_static${${CMAKE_POSTFIX_VARIABLE}}.a") + else () + set (LIBCXX_LIBS "-lc++ -lc++abi") + endif () + + set (DEFAULT_LIBS "${DEFAULT_LIBS} -Wl,-Bstatic ${LIBCXX_LIBS} ${EXCEPTION_HANDLING_LIBRARY} ${BUILTINS_LIB_PATH} -Wl,-Bdynamic") + else () + set (DEFAULT_LIBS "${DEFAULT_LIBS} -Wl,-Bstatic -lstdc++ ${EXCEPTION_HANDLING_LIBRARY} ${COVERAGE_OPTION} ${BUILTINS_LIB_PATH} -Wl,-Bdynamic") endif () # Linking with GLIBC prevents portability of binaries to older systems. @@ -255,6 +344,7 @@ endif () if (DEFAULT_LIBS) # Add default libs to all targets as the last dependency. set(CMAKE_CXX_STANDARD_LIBRARIES ${DEFAULT_LIBS}) + set(CMAKE_C_STANDARD_LIBRARIES ${DEFAULT_LIBS}) endif () if (NOT MAKE_STATIC_LIBRARIES) @@ -273,6 +363,24 @@ if (USE_INCLUDE_WHAT_YOU_USE) endif() endif () +# Using clang-tidy static analyzer http://mariobadr.com/using-clang-tidy-with-cmake-36.html https://cmake.org/cmake/help/v3.6/prop_tgt/LANG_CLANG_TIDY.html +option (ENABLE_CLANG_TIDY "Use 'clang-tidy' static analyzer" OFF) +if (ENABLE_CLANG_TIDY) + if (${CMAKE_VERSION} VERSION_LESS "3.6.0") + message(FATAL_ERROR "clang-tidy requires CMake version at least 3.6.") + endif() + find_program (CLANG_TIDY_EXE NAMES "clang-tidy" DOC "Path to clang-tidy executable") + if (NOT CLANG_TIDY_EXE) + set (USE_CLANG_TIDY 0) + message (STATUS "clang-tidy not found.") + else () + set (USE_CLANG_TIDY 1) + message (STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") + set (DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-checks=*,-clang-analyzer-alpha.*") + # You can enable it within a directory by: set (CMAKE_CXX_CLANG_TIDY "${DO_CLANG_TIDY}") + endif () +endif () + if (ENABLE_TESTS) message (STATUS "Tests are enabled") endif () @@ -296,11 +404,16 @@ if (UNBUNDLED OR NOT (OS_LINUX OR APPLE) OR ARCH_32) option (NO_WERROR "Disable -Werror compiler option" ON) endif () +if (USE_LIBCXX AND USE_INTERNAL_LIBCXX_LIBRARY) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++ -isystem ${LIBCXX_INCLUDE_DIR} -isystem ${LIBCXXABI_INCLUDE_DIR}") +endif () + message (STATUS "Building for: ${CMAKE_SYSTEM} ${CMAKE_SYSTEM_PROCESSOR} ${CMAKE_LIBRARY_ARCHITECTURE} ; USE_STATIC_LIBRARIES=${USE_STATIC_LIBRARIES} MAKE_STATIC_LIBRARIES=${MAKE_STATIC_LIBRARIES} SPLIT_SHARED=${SPLIT_SHARED_LIBRARIES} UNBUNDLED=${UNBUNDLED} CCACHE=${CCACHE_FOUND} ${CCACHE_VERSION}") include(GNUInstallDirs) include (cmake/find_contrib_lib.cmake) +find_contrib_lib(double-conversion) # Must be before parquet include (cmake/find_ssl.cmake) include (cmake/lib_name.cmake) include (cmake/find_icu.cmake) @@ -323,6 +436,7 @@ include (cmake/find_libgsasl.cmake) include (cmake/find_rdkafka.cmake) include (cmake/find_capnp.cmake) include (cmake/find_llvm.cmake) +include (cmake/find_h3.cmake) include (cmake/find_cpuid.cmake) # Freebsd, bundled if (NOT USE_CPUID) include (cmake/find_cpuinfo.cmake) # Debian @@ -334,16 +448,16 @@ include (cmake/find_pdqsort.cmake) include (cmake/find_hdfs3.cmake) # uses protobuf include (cmake/find_consistent-hashing.cmake) include (cmake/find_base64.cmake) +include (cmake/find_parquet.cmake) include (cmake/find_hyperscan.cmake) include (cmake/find_mimalloc.cmake) include (cmake/find_simdjson.cmake) include (cmake/find_rapidjson.cmake) + find_contrib_lib(cityhash) find_contrib_lib(farmhash) find_contrib_lib(metrohash) find_contrib_lib(btrie) -find_contrib_lib(double-conversion) -include (cmake/find_parquet.cmake) if (ENABLE_TESTS) include (cmake/find_gtest.cmake) @@ -354,7 +468,6 @@ include (libs/libcommon/cmake/find_gperftools.cmake) include (libs/libcommon/cmake/find_jemalloc.cmake) include (libs/libcommon/cmake/find_cctz.cmake) include (libs/libmysqlxx/cmake/find_mysqlclient.cmake) -include (libs/libdaemon/cmake/find_unwind.cmake) include (cmake/print_flags.cmake) @@ -365,50 +478,71 @@ add_subdirectory (dbms) include (cmake/print_include_directories.cmake) -if (GLIBC_COMPATIBILITY) +if (GLIBC_COMPATIBILITY OR USE_INTERNAL_UNWIND_LIBRARY_FOR_EXCEPTION_HANDLING) # FIXME: actually glibc-compatibility should always be built first, # because it's unconditionally linked via $DEFAULT_LIBS, # and these looks like the first places that get linked. - function (add_glibc_compat target_name) + function (add_default_dependencies target_name) if (TARGET ${target_name}) - add_dependencies(${target_name} glibc-compatibility) + if (GLIBC_COMPATIBILITY) + add_dependencies(${target_name} glibc-compatibility) + endif () + + if (USE_LIBCXX AND USE_INTERNAL_LIBCXX_LIBRARY) + add_dependencies(${target_name} cxx_static cxxabi_static) + endif () + + if (USE_INTERNAL_UNWIND_LIBRARY_FOR_EXCEPTION_HANDLING) + add_dependencies(${target_name} unwind_static) + endif () endif () endfunction () - add_glibc_compat(ltdl) - add_glibc_compat(zlibstatic) - add_glibc_compat(jemalloc) - add_glibc_compat(unwind) - add_glibc_compat(memcpy) - add_glibc_compat(Foundation) - add_glibc_compat(common) - add_glibc_compat(gtest) - add_glibc_compat(lz4) - add_glibc_compat(zstd) - add_glibc_compat(snappy) - add_glibc_compat(arrow) - add_glibc_compat(protoc) - add_glibc_compat(thrift_static) - add_glibc_compat(cityhash) - add_glibc_compat(farmhash) - add_glibc_compat(murmurhash) - add_glibc_compat(metrohash) - add_glibc_compat(metrohash128) - add_glibc_compat(consistent-hashing) - add_glibc_compat(double-conversion) - add_glibc_compat(cctz) - add_glibc_compat(kj) - add_glibc_compat(simdjson) - add_glibc_compat(apple_rt) - add_glibc_compat(re2) - add_glibc_compat(re2_st) - add_glibc_compat(hs_compile_shared) - add_glibc_compat(hs_exec_shared) - add_glibc_compat(hs_shared) - add_glibc_compat(widechar_width) - add_glibc_compat(string_utils) - add_glibc_compat(consistent-hashing-sumbur) - add_glibc_compat(boost_program_options_internal) - add_glibc_compat(boost_system_internal) - add_glibc_compat(boost_regex_internal) + add_default_dependencies(ltdl) + add_default_dependencies(zlibstatic) + add_default_dependencies(jemalloc) + add_default_dependencies(memcpy) + add_default_dependencies(Foundation) + add_default_dependencies(common) + add_default_dependencies(gtest) + add_default_dependencies(lz4) + add_default_dependencies(zstd) + add_default_dependencies(snappy) + add_default_dependencies(arrow) + add_default_dependencies(protoc) + add_default_dependencies(thrift_static) + add_default_dependencies(cityhash) + add_default_dependencies(farmhash) + add_default_dependencies(murmurhash) + add_default_dependencies(metrohash) + add_default_dependencies(metrohash128) + add_default_dependencies(consistent-hashing) + add_default_dependencies(double-conversion) + add_default_dependencies(cctz) + add_default_dependencies(kj) + add_default_dependencies(simdjson) + add_default_dependencies(apple_rt) + add_default_dependencies(h3) + add_default_dependencies(re2) + add_default_dependencies(re2_st) + add_default_dependencies(hs_compile_shared) + add_default_dependencies(hs_exec_shared) + add_default_dependencies(hs_shared) + add_default_dependencies(widechar_width) + add_default_dependencies(string_utils) + add_default_dependencies(consistent-hashing-sumbur) + add_default_dependencies(boost_program_options_internal) + add_default_dependencies(boost_system_internal) + add_default_dependencies(boost_regex_internal) + add_default_dependencies(roaring) + add_default_dependencies(btrie) + add_default_dependencies(cpuid) + add_default_dependencies(mysqlclient) + add_default_dependencies(zlib) + add_default_dependencies(thrift) + add_default_dependencies(brotli) + add_default_dependencies(libprotobuf) + add_default_dependencies(base64) + add_default_dependencies(readpassphrase) + add_default_dependencies(unwind_static) endif () diff --git a/LICENSE b/LICENSE index 540e18567c6..ef36c40c4b0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,5 @@ +Copyright 2016-2019 Yandex LLC + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/README.md b/README.md index e3c4f407c8d..6538fbee0eb 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ ClickHouse is an open-source column-oriented database management system that all * [Official website](https://clickhouse.yandex/) has quick high-level overview of ClickHouse on main page. * [Tutorial](https://clickhouse.yandex/tutorial.html) shows how to set up and query small ClickHouse cluster. * [Documentation](https://clickhouse.yandex/docs/en/) provides more in-depth information. +* [YouTube channel](https://www.youtube.com/channel/UChtmrD-dsdpspr42P_PyRAw) has a lot of content about ClickHouse in video format. * [Blog](https://clickhouse.yandex/blog/en/) contains various ClickHouse-related articles, as well as announces and reports about events. * [Contacts](https://clickhouse.yandex/#contacts) can help to get your questions answered if there are any. * You can also [fill this form](https://forms.yandex.com/surveys/meet-yandex-clickhouse-team/) to meet Yandex ClickHouse team in person. diff --git a/ci/install-os-packages.sh b/ci/install-os-packages.sh index fe5b4f84833..38fa6dbba15 100755 --- a/ci/install-os-packages.sh +++ b/ci/install-os-packages.sh @@ -7,9 +7,9 @@ WHAT=$1 [[ $EUID -ne 0 ]] && SUDO=sudo -command -v apt-get && PACKAGE_MANAGER=apt command -v yum && PACKAGE_MANAGER=yum command -v pkg && PACKAGE_MANAGER=pkg +command -v apt-get && PACKAGE_MANAGER=apt case $PACKAGE_MANAGER in diff --git a/cmake/find_cxx.cmake b/cmake/find_cxx.cmake new file mode 100644 index 00000000000..a10c3259ad9 --- /dev/null +++ b/cmake/find_cxx.cmake @@ -0,0 +1,23 @@ +if (NOT APPLE) + option (USE_INTERNAL_LIBCXX_LIBRARY "Set to FALSE to use system libcxx library instead of bundled" ${NOT_UNBUNDLED}) +endif () + +if (USE_INTERNAL_LIBCXX_LIBRARY AND NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/libcxx/include/vector") + message (WARNING "submodule contrib/libcxx is missing. to fix try run: \n git submodule update --init --recursive") + set (USE_INTERNAL_LIBCXX_LIBRARY 0) +endif () + +if (NOT USE_INTERNAL_LIBCXX_LIBRARY) + find_library (LIBCXX_LIBRARY c++) + find_path (LIBCXX_INCLUDE_DIR NAMES vector PATHS ${LIBCXX_INCLUDE_PATHS}) +endif () + +if (LIBCXX_LIBRARY AND LIBCXX_INCLUDE_DIR) +else () + set (LIBCXX_INCLUDE_DIR ${ClickHouse_SOURCE_DIR}/contrib/libcxx/include) + set (USE_INTERNAL_LIBCXX_LIBRARY 1) + set (LIBCXX_LIBRARY cxx_static) + set (HAVE_LIBCXX 1) +endif () + +message (STATUS "Using libcxx: ${LIBCXX_INCLUDE_DIR} : ${LIBCXX_LIBRARY}") diff --git a/cmake/find_cxxabi.cmake b/cmake/find_cxxabi.cmake new file mode 100644 index 00000000000..8f240597bc4 --- /dev/null +++ b/cmake/find_cxxabi.cmake @@ -0,0 +1,22 @@ +if (NOT APPLE) + option (USE_INTERNAL_LIBCXXABI_LIBRARY "Set to FALSE to use system libcxxabi library instead of bundled" ${NOT_UNBUNDLED}) +endif () + +if (USE_INTERNAL_LIBCXXABI_LIBRARY AND NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/libcxxabi/src") + message (WARNING "submodule contrib/libcxxabi is missing. to fix try run: \n git submodule update --init --recursive") + set (USE_INTERNAL_LIBCXXABI_LIBRARY 0) +endif () + +if (NOT USE_INTERNAL_LIBCXXABI_LIBRARY) + find_library (LIBCXXABI_LIBRARY cxxabi) + find_path (LIBCXXABI_INCLUDE_DIR NAMES vector PATHS ${LIBCXXABI_INCLUDE_PATHS}) +endif () + +if (LIBCXXABI_LIBRARY AND LIBCXXABI_INCLUDE_DIR) +else () + set (LIBCXXABI_INCLUDE_DIR ${ClickHouse_SOURCE_DIR}/contrib/libcxxabi/include) + set (USE_INTERNAL_LIBCXXABI_LIBRARY 1) + set (LIBCXXABI_LIBRARY cxxabi_static) +endif () + +message (STATUS "Using libcxxabi: ${LIBCXXABI_INCLUDE_DIR} : ${LIBCXXABI_LIBRARY}") diff --git a/cmake/find_h3.cmake b/cmake/find_h3.cmake new file mode 100644 index 00000000000..802f5aff05e --- /dev/null +++ b/cmake/find_h3.cmake @@ -0,0 +1,19 @@ +option (USE_INTERNAL_H3_LIBRARY "Set to FALSE to use system h3 library instead of bundled" ${NOT_UNBUNDLED}) + +set (H3_INCLUDE_PATHS /usr/local/include/h3) + +if (USE_INTERNAL_H3_LIBRARY) + set (H3_LIBRARY h3) + set (H3_INCLUDE_DIR ${ClickHouse_SOURCE_DIR}/contrib/h3/src/h3lib/include) +else () + find_library (H3_LIBRARY h3) + find_path (H3_INCLUDE_DIR NAMES h3api.h PATHS ${H3_INCLUDE_PATHS}) +endif () + +if (H3_LIBRARY AND H3_INCLUDE_DIR) + set (USE_H3 1) +else () + set (USE_H3 0) +endif () + +message (STATUS "Using h3=${USE_H3}: ${H3_INCLUDE_DIR} : ${H3_LIBRARY}") diff --git a/libs/libdaemon/cmake/find_unwind.cmake b/cmake/find_unwind.cmake similarity index 81% rename from libs/libdaemon/cmake/find_unwind.cmake rename to cmake/find_unwind.cmake index 876bc7298e8..25e088e8deb 100644 --- a/libs/libdaemon/cmake/find_unwind.cmake +++ b/cmake/find_unwind.cmake @@ -25,11 +25,11 @@ if (NOT USE_INTERNAL_UNWIND_LIBRARY) int main () { ucontext_t context; unw_cursor_t cursor; - unw_init_local2(&cursor, &context, UNW_INIT_SIGNAL_FRAME); + unw_init_local(&cursor, &context); return 0; } - " HAVE_UNW_INIT_LOCAL2) - if (NOT HAVE_UNW_INIT_LOCAL2) + " HAVE_UNW_INIT_LOCAL) + if (NOT HAVE_UNW_INIT_LOCAL) set(UNWIND_LIBRARY "") set(UNWIND_INCLUDE_DIR "") endif () @@ -38,10 +38,17 @@ endif () if (UNWIND_LIBRARY AND UNWIND_INCLUDE_DIR) set (USE_UNWIND 1) -elseif (CMAKE_SYSTEM MATCHES "Linux" AND NOT ARCH_ARM AND NOT ARCH_32) +elseif (CMAKE_SYSTEM MATCHES "Linux" AND NOT ARCH_ARM AND NOT ARCH_32 AND NOT UNBUNDLED) set (USE_INTERNAL_UNWIND_LIBRARY 1) + + set (PACKAGE_VERSION "9.0.0svn" CACHE STRING "") + set (UNWIND_INCLUDE_DIR "${ClickHouse_SOURCE_DIR}/contrib/libunwind/include") - set (UNWIND_LIBRARY unwind) + + set (LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") + set (LIBUNWIND_ENABLE_STATIC ON CACHE BOOL "") + set (UNWIND_LIBRARY unwind_static) + set (USE_UNWIND 1) endif () diff --git a/cmake/sanitize.cmake b/cmake/sanitize.cmake index 1d8ed9461eb..196a66e6845 100644 --- a/cmake/sanitize.cmake +++ b/cmake/sanitize.cmake @@ -6,28 +6,39 @@ if (SANITIZE) if (SANITIZE STREQUAL "address") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAN_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAN_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope") + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope") + endif() if (MAKE_STATIC_LIBRARIES AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libasan") endif () + elseif (SANITIZE STREQUAL "memory") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAN_FLAGS} -fsanitize=memory") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAN_FLAGS} -fsanitize=memory") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=memory") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAN_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAN_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins") + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=memory") + endif() if (MAKE_STATIC_LIBRARIES AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libmsan") endif () + elseif (SANITIZE STREQUAL "thread") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAN_FLAGS} -fsanitize=thread") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAN_FLAGS} -fsanitize=thread") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread") + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread") + endif() if (MAKE_STATIC_LIBRARIES AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libtsan") endif () + elseif (SANITIZE STREQUAL "undefined") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SAN_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SAN_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined") + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined") + endif() if (MAKE_STATIC_LIBRARIES AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libubsan") endif () diff --git a/cmake/use_libcxx.cmake b/cmake/use_libcxx.cmake deleted file mode 100644 index 29ac9406fe0..00000000000 --- a/cmake/use_libcxx.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Uses MAKE_STATIC_LIBRARIES - - -set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package (Threads) - -include (cmake/test_compiler.cmake) -include (cmake/arch.cmake) - -if (OS_LINUX AND COMPILER_CLANG) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") - - option (USE_LIBCXX "Use libc++ and libc++abi instead of libstdc++ (only make sense on Linux with Clang)" ${HAVE_LIBCXX}) - - if (USE_LIBCXX) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") # Ok for clang6, for older can cause 'not used option' warning - set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_LIBCPP_DEBUG=0") # More checks in debug build. - endif () -endif () - -if (USE_STATIC_LIBRARIES AND HAVE_NO_PIE) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG_NO_PIE}") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAG_NO_PIE}") -endif () diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index eb3712f4c2b..1280a309b01 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -10,6 +10,20 @@ endif () set_property(DIRECTORY PROPERTY EXCLUDE_FROM_ALL 1) + +if (USE_INTERNAL_UNWIND_LIBRARY) + add_subdirectory (libunwind-cmake) +endif () + +if (USE_LIBCXX AND USE_INTERNAL_LIBCXXABI_LIBRARY) + add_subdirectory(libcxxabi-cmake) +endif() + +if (USE_LIBCXX AND USE_INTERNAL_LIBCXX_LIBRARY) + add_subdirectory(libcxx-cmake) +endif() + + if (USE_INTERNAL_BOOST_LIBRARY) add_subdirectory (boost-cmake) endif () @@ -29,8 +43,7 @@ if (USE_INTERNAL_RE2_LIBRARY) endif () if (USE_INTERNAL_DOUBLE_CONVERSION_LIBRARY) - set (BUILD_TESTING 0 CACHE INTERNAL "") - add_subdirectory (double-conversion) + add_subdirectory (double-conversion-cmake) endif () if (USE_INTERNAL_CITYHASH_LIBRARY) @@ -52,10 +65,6 @@ if (USE_INTERNAL_BTRIE_LIBRARY) add_subdirectory (libbtrie) endif () -if (USE_INTERNAL_UNWIND_LIBRARY) - add_subdirectory (libunwind) -endif () - if (USE_INTERNAL_ZLIB_LIBRARY) set (ZLIB_ENABLE_TESTS 0 CACHE INTERNAL "") set (SKIP_INSTALL_ALL 1 CACHE INTERNAL "") @@ -106,6 +115,10 @@ if (USE_INTERNAL_CPUID_LIBRARY) add_subdirectory (libcpuid) endif () +if (USE_INTERNAL_H3_LIBRARY) + add_subdirectory(h3-cmake) +endif () + if (USE_INTERNAL_SSL_LIBRARY) if (NOT MAKE_STATIC_LIBRARIES) set (BUILD_SHARED 1) @@ -150,7 +163,7 @@ if (ENABLE_ODBC AND USE_INTERNAL_ODBC_LIBRARY) add_library(ODBC::ODBC ALIAS ${ODBC_LIBRARIES}) endif () -if (USE_INTERNAL_CAPNP_LIBRARY) +if (ENABLE_CAPNP AND USE_INTERNAL_CAPNP_LIBRARY) set (BUILD_TESTING 0 CACHE INTERNAL "") set (_save ${CMAKE_CXX_EXTENSIONS}) set (CMAKE_CXX_EXTENSIONS) @@ -247,7 +260,6 @@ if(USE_INTERNAL_GTEST_LIBRARY) add_subdirectory(${ClickHouse_SOURCE_DIR}/contrib/googletest/googletest ${CMAKE_CURRENT_BINARY_DIR}/googletest) # avoid problems with target_compile_definitions (gtest INTERFACE GTEST_HAS_POSIX_RE=0) - target_include_directories (gtest SYSTEM INTERFACE ${ClickHouse_SOURCE_DIR}/contrib/googletest/include) elseif(GTEST_SRC_DIR) add_subdirectory(${GTEST_SRC_DIR}/googletest ${CMAKE_CURRENT_BINARY_DIR}/googletest) target_compile_definitions(gtest INTERFACE GTEST_HAS_POSIX_RE=0) @@ -279,7 +291,7 @@ if (USE_INTERNAL_LLVM_LIBRARY) endif () if (USE_INTERNAL_LIBGSASL_LIBRARY) - add_subdirectory(libgsasl) + add_subdirectory(libgsasl) endif() if (USE_INTERNAL_LIBXML2_LIBRARY) diff --git a/contrib/double-conversion-cmake/CMakeLists.txt b/contrib/double-conversion-cmake/CMakeLists.txt new file mode 100644 index 00000000000..f91b0fb74c1 --- /dev/null +++ b/contrib/double-conversion-cmake/CMakeLists.txt @@ -0,0 +1,14 @@ +SET(LIBRARY_DIR ${ClickHouse_SOURCE_DIR}/contrib/double-conversion) + +add_library(double-conversion +${LIBRARY_DIR}/double-conversion/bignum.cc +${LIBRARY_DIR}/double-conversion/bignum-dtoa.cc +${LIBRARY_DIR}/double-conversion/cached-powers.cc +${LIBRARY_DIR}/double-conversion/diy-fp.cc +${LIBRARY_DIR}/double-conversion/double-conversion.cc +${LIBRARY_DIR}/double-conversion/fast-dtoa.cc +${LIBRARY_DIR}/double-conversion/fixed-dtoa.cc +${LIBRARY_DIR}/double-conversion/strtod.cc) + +target_include_directories(double-conversion SYSTEM PUBLIC "${LIBRARY_DIR}") + diff --git a/contrib/h3 b/contrib/h3 new file mode 160000 index 00000000000..6cfd649e8c0 --- /dev/null +++ b/contrib/h3 @@ -0,0 +1 @@ +Subproject commit 6cfd649e8c0d3ed913e8aae928a669fc3b8a2365 diff --git a/contrib/h3-cmake/CMakeLists.txt b/contrib/h3-cmake/CMakeLists.txt new file mode 100644 index 00000000000..5df0a205a34 --- /dev/null +++ b/contrib/h3-cmake/CMakeLists.txt @@ -0,0 +1,27 @@ +set(H3_SOURCE_DIR ${ClickHouse_SOURCE_DIR}/contrib/h3/src/h3lib) +set(H3_BINARY_DIR ${ClickHouse_BINARY_DIR}/contrib/h3/src/h3lib) + +set(SRCS +${H3_SOURCE_DIR}/lib/algos.c +${H3_SOURCE_DIR}/lib/baseCells.c +${H3_SOURCE_DIR}/lib/bbox.c +${H3_SOURCE_DIR}/lib/coordijk.c +${H3_SOURCE_DIR}/lib/faceijk.c +${H3_SOURCE_DIR}/lib/geoCoord.c +${H3_SOURCE_DIR}/lib/h3Index.c +${H3_SOURCE_DIR}/lib/h3UniEdge.c +${H3_SOURCE_DIR}/lib/linkedGeo.c +${H3_SOURCE_DIR}/lib/localij.c +${H3_SOURCE_DIR}/lib/mathExtensions.c +${H3_SOURCE_DIR}/lib/polygon.c +${H3_SOURCE_DIR}/lib/vec2d.c +${H3_SOURCE_DIR}/lib/vec3d.c +${H3_SOURCE_DIR}/lib/vertexGraph.c +) + +configure_file(${H3_SOURCE_DIR}/include/h3api.h.in ${H3_BINARY_DIR}/include/h3api.h) + +add_library(h3 ${SRCS}) +target_include_directories(h3 SYSTEM PUBLIC ${H3_SOURCE_DIR}/include) +target_include_directories(h3 SYSTEM PUBLIC ${H3_BINARY_DIR}/include) +target_compile_definitions(h3 PRIVATE H3_HAVE_VLA) diff --git a/contrib/libcxx b/contrib/libcxx new file mode 160000 index 00000000000..9807685d51d --- /dev/null +++ b/contrib/libcxx @@ -0,0 +1 @@ +Subproject commit 9807685d51db467e097ad5eb8d5c2c16922794b2 diff --git a/contrib/libcxx-cmake/CMakeLists.txt b/contrib/libcxx-cmake/CMakeLists.txt new file mode 100644 index 00000000000..e9ca5e1e7cd --- /dev/null +++ b/contrib/libcxx-cmake/CMakeLists.txt @@ -0,0 +1,51 @@ +set(LIBCXX_SOURCE_DIR ${ClickHouse_SOURCE_DIR}/contrib/libcxx) +#set(LIBCXX_BINARY_DIR ${ClickHouse_BINARY_DIR}/contrib/libcxx) + +set(SRCS +${LIBCXX_SOURCE_DIR}/src/optional.cpp +${LIBCXX_SOURCE_DIR}/src/variant.cpp +${LIBCXX_SOURCE_DIR}/src/chrono.cpp +${LIBCXX_SOURCE_DIR}/src/thread.cpp +${LIBCXX_SOURCE_DIR}/src/experimental/memory_resource.cpp +${LIBCXX_SOURCE_DIR}/src/iostream.cpp +${LIBCXX_SOURCE_DIR}/src/strstream.cpp +${LIBCXX_SOURCE_DIR}/src/ios.cpp +${LIBCXX_SOURCE_DIR}/src/future.cpp +${LIBCXX_SOURCE_DIR}/src/shared_mutex.cpp +${LIBCXX_SOURCE_DIR}/src/condition_variable.cpp +${LIBCXX_SOURCE_DIR}/src/hash.cpp +${LIBCXX_SOURCE_DIR}/src/string.cpp +${LIBCXX_SOURCE_DIR}/src/debug.cpp +#${LIBCXX_SOURCE_DIR}/src/support/win32/support.cpp +#${LIBCXX_SOURCE_DIR}/src/support/win32/locale_win32.cpp +#${LIBCXX_SOURCE_DIR}/src/support/win32/thread_win32.cpp +#${LIBCXX_SOURCE_DIR}/src/support/solaris/xlocale.cpp +${LIBCXX_SOURCE_DIR}/src/stdexcept.cpp +${LIBCXX_SOURCE_DIR}/src/utility.cpp +${LIBCXX_SOURCE_DIR}/src/any.cpp +${LIBCXX_SOURCE_DIR}/src/exception.cpp +${LIBCXX_SOURCE_DIR}/src/memory.cpp +${LIBCXX_SOURCE_DIR}/src/new.cpp +${LIBCXX_SOURCE_DIR}/src/valarray.cpp +${LIBCXX_SOURCE_DIR}/src/vector.cpp +${LIBCXX_SOURCE_DIR}/src/algorithm.cpp +${LIBCXX_SOURCE_DIR}/src/functional.cpp +${LIBCXX_SOURCE_DIR}/src/regex.cpp +${LIBCXX_SOURCE_DIR}/src/bind.cpp +${LIBCXX_SOURCE_DIR}/src/mutex.cpp +${LIBCXX_SOURCE_DIR}/src/charconv.cpp +${LIBCXX_SOURCE_DIR}/src/typeinfo.cpp +${LIBCXX_SOURCE_DIR}/src/locale.cpp +${LIBCXX_SOURCE_DIR}/src/filesystem/operations.cpp +${LIBCXX_SOURCE_DIR}/src/filesystem/int128_builtins.cpp +${LIBCXX_SOURCE_DIR}/src/filesystem/directory_iterator.cpp +${LIBCXX_SOURCE_DIR}/src/system_error.cpp +${LIBCXX_SOURCE_DIR}/src/random.cpp +) + +add_library(cxx_static ${SRCS}) + +target_include_directories(cxx_static PUBLIC ${LIBCXX_SOURCE_DIR}/include) +target_compile_definitions(cxx_static PRIVATE -D_LIBCPP_BUILDING_LIBRARY -DLIBCXX_BUILDING_LIBCXXABI) +target_compile_options(cxx_static PRIVATE -nostdinc++) + diff --git a/contrib/libcxxabi b/contrib/libcxxabi new file mode 160000 index 00000000000..d56efcc7a52 --- /dev/null +++ b/contrib/libcxxabi @@ -0,0 +1 @@ +Subproject commit d56efcc7a52739518dbe7df9e743073e00951fa1 diff --git a/contrib/libcxxabi-cmake/CMakeLists.txt b/contrib/libcxxabi-cmake/CMakeLists.txt new file mode 100644 index 00000000000..2abece86691 --- /dev/null +++ b/contrib/libcxxabi-cmake/CMakeLists.txt @@ -0,0 +1,34 @@ +set(LIBCXXABI_SOURCE_DIR ${ClickHouse_SOURCE_DIR}/contrib/libcxxabi) +set(LIBCXX_SOURCE_DIR ${ClickHouse_SOURCE_DIR}/contrib/libcxx) +#set(LIBCXXABI_BINARY_DIR ${ClickHouse_BINARY_DIR}/contrib/libcxxabi) + +set(SRCS +${LIBCXXABI_SOURCE_DIR}/src/stdlib_stdexcept.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_virtual.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_thread_atexit.cpp +${LIBCXXABI_SOURCE_DIR}/src/fallback_malloc.cpp +#${LIBCXXABI_SOURCE_DIR}/src/cxa_noexception.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_guard.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_default_handlers.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_personality.cpp +${LIBCXXABI_SOURCE_DIR}/src/stdlib_exception.cpp +${LIBCXXABI_SOURCE_DIR}/src/abort_message.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_demangle.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_unexpected.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_exception.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_handlers.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_exception_storage.cpp +${LIBCXXABI_SOURCE_DIR}/src/private_typeinfo.cpp +${LIBCXXABI_SOURCE_DIR}/src/stdlib_typeinfo.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_aux_runtime.cpp +${LIBCXXABI_SOURCE_DIR}/src/cxa_vector.cpp +${LIBCXXABI_SOURCE_DIR}/src/stdlib_new_delete.cpp +) + +add_library(cxxabi_static ${SRCS}) + +target_include_directories(cxxabi_static PUBLIC ${LIBCXXABI_SOURCE_DIR}/include ${LIBCXX_SOURCE_DIR}/include) +target_compile_definitions(cxxabi_static PRIVATE -D_LIBCPP_BUILDING_LIBRARY) +target_compile_options(cxxabi_static PRIVATE -nostdinc++ -fno-sanitize=undefined) # If we don't disable UBSan, infinite recursion happens in dynamic_cast. + + diff --git a/contrib/libhdfs3-cmake/CMake/Platform.cmake b/contrib/libhdfs3-cmake/CMake/Platform.cmake index 55fbf646589..d9bc760ee3f 100644 --- a/contrib/libhdfs3-cmake/CMake/Platform.cmake +++ b/contrib/libhdfs3-cmake/CMake/Platform.cmake @@ -15,9 +15,14 @@ IF(CMAKE_COMPILER_IS_GNUCXX) STRING(REGEX MATCHALL "[0-9]+" GCC_COMPILER_VERSION ${GCC_COMPILER_VERSION}) + LIST(LENGTH GCC_COMPILER_VERSION GCC_COMPILER_VERSION_LENGTH) LIST(GET GCC_COMPILER_VERSION 0 GCC_COMPILER_VERSION_MAJOR) - LIST(GET GCC_COMPILER_VERSION 0 GCC_COMPILER_VERSION_MINOR) - + if (GCC_COMPILER_VERSION_LENGTH GREATER 1) + LIST(GET GCC_COMPILER_VERSION 1 GCC_COMPILER_VERSION_MINOR) + else () + set (GCC_COMPILER_VERSION_MINOR 0) + endif () + SET(GCC_COMPILER_VERSION_MAJOR ${GCC_COMPILER_VERSION_MAJOR} CACHE INTERNAL "gcc major version") SET(GCC_COMPILER_VERSION_MINOR ${GCC_COMPILER_VERSION_MINOR} CACHE INTERNAL "gcc minor version") diff --git a/contrib/librdkafka b/contrib/librdkafka index 8681f884020..6160ec275a5 160000 --- a/contrib/librdkafka +++ b/contrib/librdkafka @@ -1 +1 @@ -Subproject commit 8681f884020e880a4c6cda3cfc672f0669e1f38e +Subproject commit 6160ec275a5bb0a4088ede3c5f2afde638bbef65 diff --git a/contrib/librdkafka-cmake/CMakeLists.txt b/contrib/librdkafka-cmake/CMakeLists.txt index 626ae8fd6a9..54149d0db6f 100644 --- a/contrib/librdkafka-cmake/CMakeLists.txt +++ b/contrib/librdkafka-cmake/CMakeLists.txt @@ -12,6 +12,7 @@ set(SRCS ${RDKAFKA_SOURCE_DIR}/rdkafka_background.c ${RDKAFKA_SOURCE_DIR}/rdkafka_broker.c ${RDKAFKA_SOURCE_DIR}/rdkafka_buf.c + ${RDKAFKA_SOURCE_DIR}/rdkafka_cert.c ${RDKAFKA_SOURCE_DIR}/rdkafka_cgrp.c ${RDKAFKA_SOURCE_DIR}/rdkafka_conf.c ${RDKAFKA_SOURCE_DIR}/rdkafka_event.c @@ -34,6 +35,7 @@ set(SRCS ${RDKAFKA_SOURCE_DIR}/rdkafka_sasl.c ${RDKAFKA_SOURCE_DIR}/rdkafka_sasl_plain.c ${RDKAFKA_SOURCE_DIR}/rdkafka_sasl_scram.c + ${RDKAFKA_SOURCE_DIR}/rdkafka_ssl.c ${RDKAFKA_SOURCE_DIR}/rdkafka_subscription.c ${RDKAFKA_SOURCE_DIR}/rdkafka_timer.c ${RDKAFKA_SOURCE_DIR}/rdkafka_topic.c diff --git a/contrib/librdkafka-cmake/config.h b/contrib/librdkafka-cmake/config.h index 403a79ea42e..bf67863ae7d 100644 --- a/contrib/librdkafka-cmake/config.h +++ b/contrib/librdkafka-cmake/config.h @@ -77,8 +77,6 @@ #define HAVE_PTHREAD_SETNAME_GNU 1 // python //#define HAVE_PYTHON 1 -// C11 threads -#if (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_THREADS__) -# define WITH_C11THREADS 1 -#endif +// disable C11 threads for compatibility with old libc +#define WITH_C11THREADS 0 #endif /* _CONFIG_H_ */ diff --git a/contrib/libunwind b/contrib/libunwind new file mode 160000 index 00000000000..ec86b1c6a2c --- /dev/null +++ b/contrib/libunwind @@ -0,0 +1 @@ +Subproject commit ec86b1c6a2c6b8ba316f429db9a6d4122dd12710 diff --git a/contrib/libunwind-cmake/CMakeLists.txt b/contrib/libunwind-cmake/CMakeLists.txt new file mode 100644 index 00000000000..3d4cd319089 --- /dev/null +++ b/contrib/libunwind-cmake/CMakeLists.txt @@ -0,0 +1,31 @@ +set(LIBUNWIND_SOURCE_DIR ${ClickHouse_SOURCE_DIR}/contrib/libunwind) + +set(LIBUNWIND_CXX_SOURCES + ${LIBUNWIND_SOURCE_DIR}/src/libunwind.cpp + ${LIBUNWIND_SOURCE_DIR}/src/Unwind-EHABI.cpp + ${LIBUNWIND_SOURCE_DIR}/src/Unwind-seh.cpp) +if (APPLE) + set(LIBUNWIND_CXX_SOURCES ${LIBUNWIND_CXX_SOURCES} ${LIBUNWIND_SOURCE_DIR}/src/Unwind_AppleExtras.cpp) +endif () + +set(LIBUNWIND_C_SOURCES + ${LIBUNWIND_SOURCE_DIR}/src/UnwindLevel1.c + ${LIBUNWIND_SOURCE_DIR}/src/UnwindLevel1-gcc-ext.c + ${LIBUNWIND_SOURCE_DIR}/src/Unwind-sjlj.c) +set_source_files_properties(${LIBUNWIND_C_SOURCES} PROPERTIES COMPILE_FLAGS "-std=c99") + +set(LIBUNWIND_ASM_SOURCES + ${LIBUNWIND_SOURCE_DIR}/src/UnwindRegistersRestore.S + ${LIBUNWIND_SOURCE_DIR}/src/UnwindRegistersSave.S) +set_source_files_properties(${LIBUNWIND_ASM_SOURCES} PROPERTIES LANGUAGE C) + +set(LIBUNWIND_SOURCES + ${LIBUNWIND_CXX_SOURCES} + ${LIBUNWIND_C_SOURCES} + ${LIBUNWIND_ASM_SOURCES}) + +add_library(unwind_static ${LIBUNWIND_SOURCES}) + +target_include_directories(unwind_static PUBLIC ${LIBUNWIND_SOURCE_DIR}/include) +target_compile_definitions(unwind_static PRIVATE -D_LIBUNWIND_NO_HEAP=1 -D_DEBUG -D_LIBUNWIND_IS_NATIVE_ONLY) +target_compile_options(unwind_static PRIVATE -fno-exceptions -funwind-tables -fno-sanitize=all -nostdinc++ -fno-rtti) diff --git a/contrib/libunwind/AUTHORS b/contrib/libunwind/AUTHORS deleted file mode 100644 index 719eee5c85a..00000000000 --- a/contrib/libunwind/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -David Mosberger diff --git a/contrib/libunwind/CMakeLists.txt b/contrib/libunwind/CMakeLists.txt deleted file mode 100644 index 80bd8a301f0..00000000000 --- a/contrib/libunwind/CMakeLists.txt +++ /dev/null @@ -1,122 +0,0 @@ -enable_language(ASM) - -if (ARCH_PPC64LE) - add_library(unwind - src/mi/init.c - src/mi/flush_cache.c - src/mi/mempool.c - src/mi/strerror.c - src/mi/_ReadULEB.c - src/mi/_ReadSLEB.c - src/mi/backtrace.c - src/mi/dyn-cancel.c - src/mi/dyn-info-list.c - src/mi/dyn-register.c - src/mi/Ldyn-extract.c - src/mi/Lfind_dynamic_proc_info.c - src/mi/Lget_accessors.c - src/mi/Lget_proc_info_by_ip.c - src/mi/Lget_proc_name.c - src/mi/Lput_dynamic_unwind_info.c - src/mi/Ldestroy_addr_space.c - src/mi/Lget_reg.c - src/mi/Lset_reg.c - src/mi/Lget_fpreg.c - src/mi/Lset_fpreg.c - src/mi/Lset_caching_policy.c - src/dwarf/Lexpr.c - src/dwarf/Lfde.c - src/dwarf/Lfind_proc_info-lsb.c - src/dwarf/Lparser.c - src/dwarf/Lpe.c - src/dwarf/global.c - src/elf64.c - src/os-linux.c - - src/ppc64/is_fpreg.c - src/ppc64/regname.c - src/ppc64/get_func_addr.c - src/ppc/Linit_local.c - src/ppc/Linit_remote.c - src/ppc/Lis_signal_frame.c - src/ppc/longjmp.S - src/ppc/Lreg_states_iterate.c - src/ppc/siglongjmp.S - src/ppc64/setcontext.S - src/ppc64/Lcreate_addr_space.c - src/ppc64/Lglobal.c - src/ppc64/Linit.c - src/ppc64/Lreg_states_iterate.c - src/ppc64/Lregs.c - src/ppc64/Lresume.c - src/ppc64/Lstep.c - src/ppc64/regname.c - src/ppc64/setcontext.S - ) -else () - add_library(unwind - src/mi/init.c - src/mi/flush_cache.c - src/mi/mempool.c - src/mi/strerror.c - src/mi/_ReadULEB.c - src/mi/_ReadSLEB.c - src/mi/backtrace.c - src/mi/dyn-cancel.c - src/mi/dyn-info-list.c - src/mi/dyn-register.c - src/mi/Ldyn-extract.c - src/mi/Lfind_dynamic_proc_info.c - src/mi/Lget_accessors.c - src/mi/Lget_proc_info_by_ip.c - src/mi/Lget_proc_name.c - src/mi/Lput_dynamic_unwind_info.c - src/mi/Ldestroy_addr_space.c - src/mi/Lget_reg.c - src/mi/Lset_reg.c - src/mi/Lget_fpreg.c - src/mi/Lset_fpreg.c - src/mi/Lset_caching_policy.c - src/dwarf/Lexpr.c - src/dwarf/Lfde.c - src/dwarf/Lfind_proc_info-lsb.c - src/dwarf/Lparser.c - src/dwarf/Lpe.c - src/dwarf/global.c - src/elf64.c - src/os-linux.c - - src/x86_64/is_fpreg.c - src/x86_64/regname.c - src/x86_64/setcontext.S - src/x86_64/Lcreate_addr_space.c - src/x86_64/Lget_save_loc.c - src/x86_64/Lglobal.c - src/x86_64/Linit.c - src/x86_64/Linit_local.c - src/x86_64/Linit_remote.c - src/x86_64/Lget_proc_info.c - src/x86_64/Lregs.c - src/x86_64/Lresume.c - src/x86_64/Lstash_frame.c - src/x86_64/Lstep.c - src/x86_64/Ltrace.c - src/x86_64/getcontext.S - src/x86_64/Los-linux.c - ) -endif() - -find_file (HAVE_ATOMIC_OPS_H "atomic_ops.h") -configure_file (config/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config/config.h) -configure_file (config/libunwind.h.in ${CMAKE_CURRENT_BINARY_DIR}/config/libunwind.h) -configure_file (config/libunwind-common.h.in ${CMAKE_CURRENT_BINARY_DIR}/config/libunwind-common.h) -configure_file (config/tdep/libunwind_i.h.in ${CMAKE_CURRENT_BINARY_DIR}/config/tdep/libunwind_i.h) - -target_compile_definitions (unwind PRIVATE HAVE_CONFIG_H=1 _XOPEN_SOURCE _GNU_SOURCE) -target_compile_options (unwind PRIVATE -Wno-visibility -Wno-header-guard) - -target_include_directories (unwind PUBLIC include) -target_include_directories (unwind PRIVATE include/tdep) -target_include_directories (unwind PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/config) -target_include_directories (unwind PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/config/tdep) -target_include_directories (unwind PRIVATE src) diff --git a/contrib/libunwind/COPYING b/contrib/libunwind/COPYING deleted file mode 100644 index 41e7d8a6fdb..00000000000 --- a/contrib/libunwind/COPYING +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2002 Hewlett-Packard Co. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/contrib/libunwind/README b/contrib/libunwind/README deleted file mode 100644 index 9687c3c0338..00000000000 --- a/contrib/libunwind/README +++ /dev/null @@ -1,2 +0,0 @@ -Source: https://github.com/libunwind/libunwind -Revision: 60ddc67196eafb5cafd0d89e461c9d700a697d6d diff --git a/contrib/libunwind/config/config.h.in b/contrib/libunwind/config/config.h.in deleted file mode 100644 index 7dcf38ed012..00000000000 --- a/contrib/libunwind/config/config.h.in +++ /dev/null @@ -1,236 +0,0 @@ -/* include/config.h. Generated from config.h.in by configure. */ -/* include/config.h.in. Generated from configure.ac by autoheader. */ - -/* Block signals before mutex operations */ -#define CONFIG_BLOCK_SIGNALS /**/ - -/* Enable Debug Frame */ -/* #undef CONFIG_DEBUG_FRAME */ - -/* Support for Microsoft ABI extensions */ -/* #undef CONFIG_MSABI_SUPPORT */ - -/* Define to 1 if you want every memory access validated */ -#define CONSERVATIVE_CHECKS 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ASM_PTRACE_OFFSETS_H */ - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_ATOMIC_OPS_H - -/* Define to 1 if you have the header file. */ -#define HAVE_BYTESWAP_H 1 - -/* Define to 1 if you have the declaration of `PTRACE_CONT', and to 0 if you - don't. */ -#define HAVE_DECL_PTRACE_CONT 1 - -/* Define to 1 if you have the declaration of `PTRACE_POKEDATA', and to 0 if - you don't. */ -#define HAVE_DECL_PTRACE_POKEDATA 1 - -/* Define to 1 if you have the declaration of `PTRACE_POKEUSER', and to 0 if - you don't. */ -#define HAVE_DECL_PTRACE_POKEUSER 1 - -/* Define to 1 if you have the declaration of `PTRACE_SETREGSET', and to 0 if - you don't. */ -#define HAVE_DECL_PTRACE_SETREGSET 1 - -/* Define to 1 if you have the declaration of `PTRACE_SINGLESTEP', and to 0 if - you don't. */ -#define HAVE_DECL_PTRACE_SINGLESTEP 1 - -/* Define to 1 if you have the declaration of `PTRACE_SYSCALL', and to 0 if - you don't. */ -#define HAVE_DECL_PTRACE_SYSCALL 1 - -/* Define to 1 if you have the declaration of `PTRACE_TRACEME', and to 0 if - you don't. */ -#define HAVE_DECL_PTRACE_TRACEME 1 - -/* Define to 1 if you have the declaration of `PT_CONTINUE', and to 0 if you - don't. */ -#define HAVE_DECL_PT_CONTINUE 1 - -/* Define to 1 if you have the declaration of `PT_GETFPREGS', and to 0 if you - don't. */ -#define HAVE_DECL_PT_GETFPREGS 1 - -/* Define to 1 if you have the declaration of `PT_GETREGS', and to 0 if you - don't. */ -#define HAVE_DECL_PT_GETREGS 1 - -/* Define to 1 if you have the declaration of `PT_IO', and to 0 if you don't. - */ -#define HAVE_DECL_PT_IO 0 - -/* Define to 1 if you have the declaration of `PT_STEP', and to 0 if you - don't. */ -#define HAVE_DECL_PT_STEP 1 - -/* Define to 1 if you have the declaration of `PT_SYSCALL', and to 0 if you - don't. */ -#define HAVE_DECL_PT_SYSCALL 1 - -/* Define to 1 if you have the declaration of `PT_TRACE_ME', and to 0 if you - don't. */ -#define HAVE_DECL_PT_TRACE_ME 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the `dlmodinfo' function. */ -/* #undef HAVE_DLMODINFO */ - -/* Define to 1 if you have the `dl_iterate_phdr' function. */ -#define HAVE_DL_ITERATE_PHDR 1 - -/* Define to 1 if you have the `dl_phdr_removals_counter' function. */ -/* #undef HAVE_DL_PHDR_REMOVALS_COUNTER */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ELF_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ENDIAN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_EXECINFO_H 1 - -/* Define to 1 if you have the `getunwind' function. */ -/* #undef HAVE_GETUNWIND */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_IA64INTRIN_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `uca' library (-luca). */ -/* #undef HAVE_LIBUCA */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LINK_H 1 - -/* Define if you have liblzma */ -/* #undef HAVE_LZMA */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `mincore' function. */ -#define HAVE_MINCORE 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if `dlpi_subs' is a member of `struct dl_phdr_info'. */ -#define HAVE_STRUCT_DL_PHDR_INFO_DLPI_SUBS 1 - -/* Define to 1 if the system has the type `struct elf_prstatus'. */ -#define HAVE_STRUCT_ELF_PRSTATUS 1 - -/* Define to 1 if the system has the type `struct prstatus'. */ -/* #undef HAVE_STRUCT_PRSTATUS */ - -/* Defined if __sync atomics are available */ -#define HAVE_SYNC_ATOMICS 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_ELF_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_ENDIAN_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_LINK_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_PROCFS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_PTRACE_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_UC_ACCESS_H */ - -/* Define to 1 if you have the `ttrace' function. */ -/* #undef HAVE_TTRACE */ - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Defined if __builtin_unreachable() is available */ -#define HAVE__BUILTIN_UNREACHABLE 1 - -/* Defined if __builtin___clear_cache() is available */ -#define HAVE__BUILTIN___CLEAR_CACHE 1 - -/* Define to 1 if __thread keyword is supported by the C compiler. */ -/* #undef HAVE___THREAD */ - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define LT_OBJDIR ".libs/" - -/* Name of package */ -#define PACKAGE "libunwind" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "libunwind-devel@nongnu.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "libunwind" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libunwind 1.2" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libunwind" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.2" - -/* The size of `off_t', as computed by sizeof. */ -#define SIZEOF_OFF_T 8 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -#define VERSION "1.2" - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ diff --git a/contrib/libunwind/config/libunwind-common.h.in b/contrib/libunwind/config/libunwind-common.h.in deleted file mode 100644 index ceacdb42128..00000000000 --- a/contrib/libunwind/config/libunwind-common.h.in +++ /dev/null @@ -1,279 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#define UNW_VERSION_MAJOR 1 -#define UNW_VERSION_MINOR 2 -#define UNW_VERSION_EXTRA - -#define UNW_VERSION_CODE(maj,min) (((maj) << 16) | (min)) -#define UNW_VERSION UNW_VERSION_CODE(UNW_VERSION_MAJOR, UNW_VERSION_MINOR) - -#define UNW_PASTE2(x,y) x##y -#define UNW_PASTE(x,y) UNW_PASTE2(x,y) -#define UNW_OBJ(fn) UNW_PASTE(UNW_PREFIX, fn) -#define UNW_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_), fn) - -#ifdef UNW_LOCAL_ONLY -# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_UL,UNW_TARGET),_) -#else /* !UNW_LOCAL_ONLY */ -# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_) -#endif /* !UNW_LOCAL_ONLY */ - -/* Error codes. The unwind routines return the *negated* values of - these error codes on error and a non-negative value on success. */ -typedef enum - { - UNW_ESUCCESS = 0, /* no error */ - UNW_EUNSPEC, /* unspecified (general) error */ - UNW_ENOMEM, /* out of memory */ - UNW_EBADREG, /* bad register number */ - UNW_EREADONLYREG, /* attempt to write read-only register */ - UNW_ESTOPUNWIND, /* stop unwinding */ - UNW_EINVALIDIP, /* invalid IP */ - UNW_EBADFRAME, /* bad frame */ - UNW_EINVAL, /* unsupported operation or bad value */ - UNW_EBADVERSION, /* unwind info has unsupported version */ - UNW_ENOINFO /* no unwind info found */ - } -unw_error_t; - -/* The following enum defines the indices for a couple of - (pseudo-)registers which have the same meaning across all - platforms. (RO) means read-only. (RW) means read-write. General - registers (aka "integer registers") are expected to start with - index 0. The number of such registers is architecture-dependent. - The remaining indices can be used as an architecture sees fit. The - last valid register index is given by UNW_REG_LAST. */ -typedef enum - { - UNW_REG_IP = UNW_TDEP_IP, /* (rw) instruction pointer (pc) */ - UNW_REG_SP = UNW_TDEP_SP, /* (ro) stack pointer */ - UNW_REG_EH = UNW_TDEP_EH, /* (rw) exception-handling reg base */ - UNW_REG_LAST = UNW_TDEP_LAST_REG - } -unw_frame_regnum_t; - -/* Number of exception-handler argument registers: */ -#define UNW_NUM_EH_REGS UNW_TDEP_NUM_EH_REGS - -typedef enum - { - UNW_CACHE_NONE, /* no caching */ - UNW_CACHE_GLOBAL, /* shared global cache */ - UNW_CACHE_PER_THREAD /* per-thread caching */ - } -unw_caching_policy_t; - -typedef enum - { - UNW_INIT_SIGNAL_FRAME = 1, /* We know this is a signal frame */ - } -unw_init_local2_flags_t; - -typedef int unw_regnum_t; - -/* The unwind cursor starts at the youngest (most deeply nested) frame - and is used to track the frame state as the unwinder steps from - frame to frame. It is safe to make (shallow) copies of variables - of this type. */ -typedef struct unw_cursor - { - unw_word_t opaque[UNW_TDEP_CURSOR_LEN]; - } -unw_cursor_t; - -/* This type encapsulates the entire (preserved) machine-state. */ -typedef unw_tdep_context_t unw_context_t; - -/* unw_getcontext() fills the unw_context_t pointed to by UC with the - machine state as it exists at the call-site. For implementation - reasons, this needs to be a target-dependent macro. It's easiest - to think of unw_getcontext() as being identical to getcontext(). */ -#define unw_getcontext(uc) unw_tdep_getcontext(uc) - -/* Return 1 if register number R is a floating-point register, zero - otherwise. - This routine is signal-safe. */ -#define unw_is_fpreg(r) unw_tdep_is_fpreg(r) - -typedef unw_tdep_fpreg_t unw_fpreg_t; - -typedef struct unw_addr_space *unw_addr_space_t; - -/* Each target may define it's own set of flags, but bits 0-15 are - reserved for general libunwind-use. */ -#define UNW_PI_FLAG_FIRST_TDEP_BIT 16 -/* The information comes from a .debug_frame section. */ -#define UNW_PI_FLAG_DEBUG_FRAME 32 - -typedef struct unw_proc_info - { - unw_word_t start_ip; /* first IP covered by this procedure */ - unw_word_t end_ip; /* first IP NOT covered by this procedure */ -#if defined(NEED_LAST_IP) - unw_word_t last_ip; /* first IP that could begin another procedure */ -#endif - unw_word_t lsda; /* address of lang.-spec. data area (if any) */ - unw_word_t handler; /* optional personality routine */ - unw_word_t gp; /* global-pointer value for this procedure */ - unw_word_t flags; /* misc. flags */ - - int format; /* unwind-info format (arch-specific) */ - int unwind_info_size; /* size of the information (if applicable) */ - void *unwind_info; /* unwind-info (arch-specific) */ - unw_tdep_proc_info_t extra; /* target-dependent auxiliary proc-info */ - } -unw_proc_info_t; - -typedef int (*unw_reg_states_callback)(void *token, - void *reg_states_data, - size_t reg_states_data_size, - unw_word_t start_ip, unw_word_t end_ip); - -/* These are backend callback routines that provide access to the - state of a "remote" process. This can be used, for example, to - unwind another process through the ptrace() interface. */ -typedef struct unw_accessors - { - /* Look up the unwind info associated with instruction-pointer IP. - On success, the routine fills in the PROC_INFO structure. */ - int (*find_proc_info) (unw_addr_space_t, unw_word_t, unw_proc_info_t *, - int, void *); - - /* Release any resources (e.g., memory) that were allocated for - the unwind info returned in by a previous call to - find_proc_info() with NEED_UNWIND_INFO set to 1. */ - void (*put_unwind_info) (unw_addr_space_t, unw_proc_info_t *, void *); - - /* Return the list-head of the dynamically registered unwind - info. */ - int (*get_dyn_info_list_addr) (unw_addr_space_t, unw_word_t *, void *); - - /* Access aligned word at address ADDR. The value is returned - according to the endianness of the host (e.g., if the host is - little-endian and the target is big-endian, access_mem() needs - to byte-swap the value before returning it). */ - int (*access_mem) (unw_addr_space_t, unw_word_t, unw_word_t *, int, - void *); - - /* Access register number REG at address ADDR. */ - int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, int, - void *); - - /* Access register number REG at address ADDR. */ - int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, - unw_fpreg_t *, int, void *); - - int (*resume) (unw_addr_space_t, unw_cursor_t *, void *); - - /* Optional call back to obtain the name of a (static) procedure. - Dynamically generated procedures are handled automatically by - libunwind. This callback is optional and may be set to - NULL. */ - int (*get_proc_name) (unw_addr_space_t, unw_word_t, char *, size_t, - unw_word_t *, void *); - } -unw_accessors_t; - -typedef enum unw_save_loc_type - { - UNW_SLT_NONE, /* register is not saved ("not an l-value") */ - UNW_SLT_MEMORY, /* register has been saved in memory */ - UNW_SLT_REG /* register has been saved in (another) register */ - } -unw_save_loc_type_t; - -typedef struct unw_save_loc - { - unw_save_loc_type_t type; - union - { - unw_word_t addr; /* valid if type==UNW_SLT_MEMORY */ - unw_regnum_t regnum; /* valid if type==UNW_SLT_REG */ - } - u; - unw_tdep_save_loc_t extra; /* target-dependent additional information */ - } -unw_save_loc_t; - -/* These routines work both for local and remote unwinding. */ - -#define unw_local_addr_space UNW_OBJ(local_addr_space) -#define unw_create_addr_space UNW_OBJ(create_addr_space) -#define unw_destroy_addr_space UNW_OBJ(destroy_addr_space) -#define unw_get_accessors UNW_ARCH_OBJ(get_accessors) -#define unw_init_local UNW_OBJ(init_local) -#define unw_init_local2 UNW_OBJ(init_local2) -#define unw_init_remote UNW_OBJ(init_remote) -#define unw_step UNW_OBJ(step) -#define unw_resume UNW_OBJ(resume) -#define unw_get_proc_info UNW_OBJ(get_proc_info) -#define unw_get_proc_info_by_ip UNW_OBJ(get_proc_info_by_ip) -#define unw_reg_states_iterate UNW_OBJ(reg_states_iterate) -#define unw_apply_reg_state UNW_OBJ(apply_reg_state) -#define unw_get_reg UNW_OBJ(get_reg) -#define unw_set_reg UNW_OBJ(set_reg) -#define unw_get_fpreg UNW_OBJ(get_fpreg) -#define unw_set_fpreg UNW_OBJ(set_fpreg) -#define unw_get_save_loc UNW_OBJ(get_save_loc) -#define unw_is_signal_frame UNW_OBJ(is_signal_frame) -#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame) -#define unw_get_proc_name UNW_OBJ(get_proc_name) -#define unw_set_caching_policy UNW_OBJ(set_caching_policy) -#define unw_set_cache_size UNW_OBJ(set_cache_size) -#define unw_regname UNW_ARCH_OBJ(regname) -#define unw_flush_cache UNW_ARCH_OBJ(flush_cache) -#define unw_strerror UNW_ARCH_OBJ(strerror) - -extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int); -extern void unw_destroy_addr_space (unw_addr_space_t); -extern unw_accessors_t *unw_get_accessors (unw_addr_space_t); -extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t); -extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t); -extern int unw_set_cache_size (unw_addr_space_t, size_t, int); -extern const char *unw_regname (unw_regnum_t); - -extern int unw_init_local (unw_cursor_t *, unw_context_t *); -extern int unw_init_local2 (unw_cursor_t *, unw_context_t *, int); -extern int unw_init_remote (unw_cursor_t *, unw_addr_space_t, void *); -extern int unw_step (unw_cursor_t *); -extern int unw_resume (unw_cursor_t *); -extern int unw_get_proc_info (unw_cursor_t *, unw_proc_info_t *); -extern int unw_get_proc_info_by_ip (unw_addr_space_t, unw_word_t, - unw_proc_info_t *, void *); -extern int unw_reg_states_iterate (unw_cursor_t *, unw_reg_states_callback, void *); -extern int unw_apply_reg_state (unw_cursor_t *, void *); -extern int unw_get_reg (unw_cursor_t *, int, unw_word_t *); -extern int unw_set_reg (unw_cursor_t *, int, unw_word_t); -extern int unw_get_fpreg (unw_cursor_t *, int, unw_fpreg_t *); -extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t); -extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *); -extern int unw_is_signal_frame (unw_cursor_t *); -extern int unw_handle_signal_frame (unw_cursor_t *); -extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *); -extern const char *unw_strerror (int); -extern int unw_backtrace (void **, int); - -extern unw_addr_space_t unw_local_addr_space; diff --git a/contrib/libunwind/config/libunwind.h.in b/contrib/libunwind/config/libunwind.h.in deleted file mode 100644 index e3ca06274b4..00000000000 --- a/contrib/libunwind/config/libunwind.h.in +++ /dev/null @@ -1,36 +0,0 @@ -/* Provide a real file - not a symlink - as it would cause multiarch conflicts - when multiple different arch releases are installed simultaneously. */ - -#ifndef UNW_REMOTE_ONLY - -#if defined __aarch64__ -#include "libunwind-aarch64.h" -#elif defined __arm__ -# include "libunwind-arm.h" -#elif defined __hppa__ -# include "libunwind-hppa.h" -#elif defined __ia64__ -# include "libunwind-ia64.h" -#elif defined __mips__ -# include "libunwind-mips.h" -#elif defined __powerpc__ && !defined __powerpc64__ -# include "libunwind-ppc32.h" -#elif defined __powerpc64__ -# include "libunwind-ppc64.h" -#elif defined __sh__ -# include "libunwind-sh.h" -#elif defined __i386__ -# include "libunwind-x86.h" -#elif defined __x86_64__ -# include "libunwind-x86_64.h" -#elif defined __tilegx__ -# include "libunwind-tilegx.h" -#else -# error "Unsupported arch" -#endif - -#else /* UNW_REMOTE_ONLY */ - -# include "libunwind-x86_64.h" - -#endif /* UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/config/tdep/libunwind_i.h.in b/contrib/libunwind/config/tdep/libunwind_i.h.in deleted file mode 100644 index d24404c5bff..00000000000 --- a/contrib/libunwind/config/tdep/libunwind_i.h.in +++ /dev/null @@ -1,37 +0,0 @@ -/* Provide a real file - not a symlink - as it would cause multiarch conflicts - when multiple different arch releases are installed simultaneously. */ - -#ifndef UNW_REMOTE_ONLY - -#if defined __aarch64__ -# include "tdep-aarch64/libunwind_i.h" -#elif defined __arm__ -# include "tdep-arm/libunwind_i.h" -#elif defined __hppa__ -# include "tdep-hppa/libunwind_i.h" -#elif defined __ia64__ -# include "tdep-ia64/libunwind_i.h" -#elif defined __mips__ -# include "tdep-mips/libunwind_i.h" -#elif defined __powerpc__ && !defined __powerpc64__ -# include "tdep-ppc32/libunwind_i.h" -#elif defined __powerpc64__ -# include "tdep-ppc64/libunwind_i.h" -#elif defined __sh__ -# include "tdep-sh/libunwind_i.h" -#elif defined __i386__ -# include "tdep-x86/libunwind_i.h" -#elif defined __x86_64__ -# include "tdep-x86_64/libunwind_i.h" -#elif defined __tilegx__ -# include "tdep-tilegx/libunwind_i.h" -#else -# error "Unsupported arch" -#endif - - -#else /* UNW_REMOTE_ONLY */ - -# include "tdep-x86_64/libunwind_i.h" - -#endif /* UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/include/compiler.h b/contrib/libunwind/include/compiler.h deleted file mode 100644 index abd424d8ab1..00000000000 --- a/contrib/libunwind/include/compiler.h +++ /dev/null @@ -1,74 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2005 Hewlett-Packard Co - Copyright (C) 2007 David Mosberger-Tang - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Compiler specific useful bits that are used in libunwind, and also in the - * tests. */ - -#ifndef COMPILER_H -#define COMPILER_H - -#ifdef __GNUC__ -# define ALIGNED(x) __attribute__((aligned(x))) -# define CONST_ATTR __attribute__((__const__)) -# define UNUSED __attribute__((unused)) -# define NOINLINE __attribute__((noinline)) -# define NORETURN __attribute__((noreturn)) -# define ALIAS(name) __attribute__((alias (#name))) -# if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) -# define ALWAYS_INLINE inline __attribute__((always_inline)) -# define HIDDEN __attribute__((visibility ("hidden"))) -# define PROTECTED __attribute__((visibility ("protected"))) -# else -# define ALWAYS_INLINE -# define HIDDEN -# define PROTECTED -# endif -# define WEAK __attribute__((weak)) -# if (__GNUC__ >= 3) -# define likely(x) __builtin_expect ((x), 1) -# define unlikely(x) __builtin_expect ((x), 0) -# else -# define likely(x) (x) -# define unlikely(x) (x) -# endif -#else -# define ALIGNED(x) -# define ALWAYS_INLINE -# define CONST_ATTR -# define UNUSED -# define NOINLINE -# define NORETURN -# define ALIAS(name) -# define HIDDEN -# define PROTECTED -# define WEAK -# define likely(x) (x) -# define unlikely(x) (x) -#endif - -#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) - -#endif /* COMPILER_H */ diff --git a/contrib/libunwind/include/dwarf-eh.h b/contrib/libunwind/include/dwarf-eh.h deleted file mode 100644 index e03750760c5..00000000000 --- a/contrib/libunwind/include/dwarf-eh.h +++ /dev/null @@ -1,128 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_eh_h -#define dwarf_eh_h - -#include "dwarf.h" - -/* This header file defines the format of a DWARF exception-header - section (.eh_frame_hdr, pointed to by program-header - PT_GNU_EH_FRAME). The exception-header is self-describing in the - sense that the format of the addresses contained in it is expressed - as a one-byte type-descriptor called a "pointer-encoding" (PE). - - The exception header encodes the address of the .eh_frame section - and optionally contains a binary search table for the - Frame Descriptor Entries (FDEs) in the .eh_frame. The contents of - .eh_frame has the format described by the DWARF v3 standard - (http://www.eagercon.com/dwarf/dwarf3std.htm), except that code - addresses may be encoded in different ways. Also, .eh_frame has - augmentations that allow encoding a language-specific data-area - (LSDA) pointer and a pointer to a personality-routine. - - Details: - - The Common Information Entry (CIE) associated with an FDE may - contain an augmentation string. Each character in this string has - a specific meaning and either one or two associated operands. The - operands are stored in an augmentation body which appears right - after the "return_address_register" member and before the - "initial_instructions" member. The operands appear in the order - in which the characters appear in the string. For example, if the - augmentation string is "zL", the operand for 'z' would be first in - the augmentation body and the operand for 'L' would be second. - The following characters are supported for the CIE augmentation - string: - - 'z': The operand for this character is a uleb128 value that gives the - length of the CIE augmentation body, not counting the length - of the uleb128 operand itself. If present, this code must - appear as the first character in the augmentation body. - - 'L': Indicates that the FDE's augmentation body contains an LSDA - pointer. The operand for this character is a single byte - that specifies the pointer-encoding (PE) that is used for - the LSDA pointer. - - 'R': Indicates that the code-pointers (FDE members - "initial_location" and "address_range" and the operand for - DW_CFA_set_loc) in the FDE have a non-default encoding. The - operand for this character is a single byte that specifies - the pointer-encoding (PE) that is used for the - code-pointers. Note: the "address_range" member is always - encoded as an absolute value. Apart from that, the specified - FDE pointer-encoding applies. - - 'P': Indicates the presence of a personality routine (handler). - The first operand for this character specifies the - pointer-encoding (PE) that is used for the second operand, - which specifies the address of the personality routine. - - If the augmentation string contains any other characters, the - remainder of the augmentation string should be ignored. - Furthermore, if the size of the augmentation body is unknown - (i.e., 'z' is not the first character of the augmentation string), - then the entire CIE as well all associated FDEs must be ignored. - - A Frame Descriptor Entries (FDE) may contain an augmentation body - which, if present, appears right after the "address_range" member - and before the "instructions" member. The contents of this body - is implicitly defined by the augmentation string of the associated - CIE. The meaning of the characters in the CIE's augmentation - string as far as FDEs are concerned is as follows: - - 'z': The first operand in the FDE's augmentation body specifies - the total length of the augmentation body as a uleb128 (not - counting the length of the uleb128 operand itself). - - 'L': The operand for this character is an LSDA pointer, encoded - in the format specified by the corresponding operand in the - CIE's augmentation body. - -*/ - -#define DW_EH_VERSION 1 /* The version we're implementing */ - -struct __attribute__((packed)) dwarf_eh_frame_hdr - { - unsigned char version; - unsigned char eh_frame_ptr_enc; - unsigned char fde_count_enc; - unsigned char table_enc; - Elf_W (Addr) eh_frame; - /* The rest of the header is variable-length and consists of the - following members: - - encoded_t fde_count; - struct - { - encoded_t start_ip; // first address covered by this FDE - encoded_t fde_addr; // address of the FDE - } - binary_search_table[fde_count]; */ - }; - -#endif /* dwarf_eh_h */ diff --git a/contrib/libunwind/include/dwarf.h b/contrib/libunwind/include/dwarf.h deleted file mode 100644 index db2a76972d1..00000000000 --- a/contrib/libunwind/include/dwarf.h +++ /dev/null @@ -1,448 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_h -#define dwarf_h - -#include - -struct dwarf_cursor; /* forward-declaration */ -struct elf_dyn_info; - -#include "dwarf-config.h" - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifndef UNW_REMOTE_ONLY - #if defined(HAVE_LINK_H) - #include - #elif defined(HAVE_SYS_LINK_H) - #include - #else - #error Could not find - #endif -#endif - -#include - -/* DWARF expression opcodes. */ - -typedef enum - { - DW_OP_addr = 0x03, - DW_OP_deref = 0x06, - DW_OP_const1u = 0x08, - DW_OP_const1s = 0x09, - DW_OP_const2u = 0x0a, - DW_OP_const2s = 0x0b, - DW_OP_const4u = 0x0c, - DW_OP_const4s = 0x0d, - DW_OP_const8u = 0x0e, - DW_OP_const8s = 0x0f, - DW_OP_constu = 0x10, - DW_OP_consts = 0x11, - DW_OP_dup = 0x12, - DW_OP_drop = 0x13, - DW_OP_over = 0x14, - DW_OP_pick = 0x15, - DW_OP_swap = 0x16, - DW_OP_rot = 0x17, - DW_OP_xderef = 0x18, - DW_OP_abs = 0x19, - DW_OP_and = 0x1a, - DW_OP_div = 0x1b, - DW_OP_minus = 0x1c, - DW_OP_mod = 0x1d, - DW_OP_mul = 0x1e, - DW_OP_neg = 0x1f, - DW_OP_not = 0x20, - DW_OP_or = 0x21, - DW_OP_plus = 0x22, - DW_OP_plus_uconst = 0x23, - DW_OP_shl = 0x24, - DW_OP_shr = 0x25, - DW_OP_shra = 0x26, - DW_OP_xor = 0x27, - DW_OP_skip = 0x2f, - DW_OP_bra = 0x28, - DW_OP_eq = 0x29, - DW_OP_ge = 0x2a, - DW_OP_gt = 0x2b, - DW_OP_le = 0x2c, - DW_OP_lt = 0x2d, - DW_OP_ne = 0x2e, - DW_OP_lit0 = 0x30, - DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4, DW_OP_lit5, - DW_OP_lit6, DW_OP_lit7, DW_OP_lit8, DW_OP_lit9, DW_OP_lit10, - DW_OP_lit11, DW_OP_lit12, DW_OP_lit13, DW_OP_lit14, DW_OP_lit15, - DW_OP_lit16, DW_OP_lit17, DW_OP_lit18, DW_OP_lit19, DW_OP_lit20, - DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24, DW_OP_lit25, - DW_OP_lit26, DW_OP_lit27, DW_OP_lit28, DW_OP_lit29, DW_OP_lit30, - DW_OP_lit31, - DW_OP_reg0 = 0x50, - DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4, DW_OP_reg5, - DW_OP_reg6, DW_OP_reg7, DW_OP_reg8, DW_OP_reg9, DW_OP_reg10, - DW_OP_reg11, DW_OP_reg12, DW_OP_reg13, DW_OP_reg14, DW_OP_reg15, - DW_OP_reg16, DW_OP_reg17, DW_OP_reg18, DW_OP_reg19, DW_OP_reg20, - DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24, DW_OP_reg25, - DW_OP_reg26, DW_OP_reg27, DW_OP_reg28, DW_OP_reg29, DW_OP_reg30, - DW_OP_reg31, - DW_OP_breg0 = 0x70, - DW_OP_breg1, DW_OP_breg2, DW_OP_breg3, DW_OP_breg4, DW_OP_breg5, - DW_OP_breg6, DW_OP_breg7, DW_OP_breg8, DW_OP_breg9, DW_OP_breg10, - DW_OP_breg11, DW_OP_breg12, DW_OP_breg13, DW_OP_breg14, DW_OP_breg15, - DW_OP_breg16, DW_OP_breg17, DW_OP_breg18, DW_OP_breg19, DW_OP_breg20, - DW_OP_breg21, DW_OP_breg22, DW_OP_breg23, DW_OP_breg24, DW_OP_breg25, - DW_OP_breg26, DW_OP_breg27, DW_OP_breg28, DW_OP_breg29, DW_OP_breg30, - DW_OP_breg31, - DW_OP_regx = 0x90, - DW_OP_fbreg = 0x91, - DW_OP_bregx = 0x92, - DW_OP_piece = 0x93, - DW_OP_deref_size = 0x94, - DW_OP_xderef_size = 0x95, - DW_OP_nop = 0x96, - DW_OP_push_object_address = 0x97, - DW_OP_call2 = 0x98, - DW_OP_call4 = 0x99, - DW_OP_call_ref = 0x9a, - DW_OP_lo_user = 0xe0, - DW_OP_hi_user = 0xff - } -dwarf_expr_op_t; - -#define DWARF_CIE_VERSION 3 /* GCC emits version 1??? */ - -#define DWARF_CFA_OPCODE_MASK 0xc0 -#define DWARF_CFA_OPERAND_MASK 0x3f - -typedef enum - { - DW_CFA_advance_loc = 0x40, - DW_CFA_offset = 0x80, - DW_CFA_restore = 0xc0, - DW_CFA_nop = 0x00, - DW_CFA_set_loc = 0x01, - DW_CFA_advance_loc1 = 0x02, - DW_CFA_advance_loc2 = 0x03, - DW_CFA_advance_loc4 = 0x04, - DW_CFA_offset_extended = 0x05, - DW_CFA_restore_extended = 0x06, - DW_CFA_undefined = 0x07, - DW_CFA_same_value = 0x08, - DW_CFA_register = 0x09, - DW_CFA_remember_state = 0x0a, - DW_CFA_restore_state = 0x0b, - DW_CFA_def_cfa = 0x0c, - DW_CFA_def_cfa_register = 0x0d, - DW_CFA_def_cfa_offset = 0x0e, - DW_CFA_def_cfa_expression = 0x0f, - DW_CFA_expression = 0x10, - DW_CFA_offset_extended_sf = 0x11, - DW_CFA_def_cfa_sf = 0x12, - DW_CFA_def_cfa_offset_sf = 0x13, - DW_CFA_val_expression = 0x16, - DW_CFA_lo_user = 0x1c, - DW_CFA_MIPS_advance_loc8 = 0x1d, - DW_CFA_GNU_window_save = 0x2d, - DW_CFA_GNU_args_size = 0x2e, - DW_CFA_GNU_negative_offset_extended = 0x2f, - DW_CFA_hi_user = 0x3c - } -dwarf_cfa_t; - -/* DWARF Pointer-Encoding (PEs). - - Pointer-Encodings were invented for the GCC exception-handling - support for C++, but they represent a rather generic way of - describing the format in which an address/pointer is stored and - hence we include the definitions here, in the main dwarf.h file. - The Pointer-Encoding format is partially documented in Linux Base - Spec v1.3 (http://www.linuxbase.org/spec/). The rest is reverse - engineered from GCC. - -*/ -#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */ -#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */ -/* Flag bit. If set, the resulting pointer is the address of the word - that contains the final address. */ -#define DW_EH_PE_indirect 0x80 - -/* Pointer-encoding formats: */ -#define DW_EH_PE_omit 0xff -#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */ -#define DW_EH_PE_uleb128 0x01 /* unsigned LE base-128 value */ -#define DW_EH_PE_udata2 0x02 /* unsigned 16-bit value */ -#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */ -#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */ -#define DW_EH_PE_sleb128 0x09 /* signed LE base-128 value */ -#define DW_EH_PE_sdata2 0x0a /* signed 16-bit value */ -#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */ -#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */ - -/* Pointer-encoding application: */ -#define DW_EH_PE_absptr 0x00 /* absolute value */ -#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */ -#define DW_EH_PE_textrel 0x20 /* text-relative (GCC-specific???) */ -#define DW_EH_PE_datarel 0x30 /* data-relative */ -/* The following are not documented by LSB v1.3, yet they are used by - GCC, presumably they aren't documented by LSB since they aren't - used on Linux: */ -#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */ -#define DW_EH_PE_aligned 0x50 /* aligned pointer */ - -extern struct mempool dwarf_reg_state_pool; -extern struct mempool dwarf_cie_info_pool; - -typedef enum - { - DWARF_WHERE_UNDEF, /* register isn't saved at all */ - DWARF_WHERE_SAME, /* register has same value as in prev. frame */ - DWARF_WHERE_CFAREL, /* register saved at CFA-relative address */ - DWARF_WHERE_REG, /* register saved in another register */ - DWARF_WHERE_EXPR, /* register saved */ - DWARF_WHERE_VAL_EXPR, /* register has computed value */ - } -dwarf_where_t; - -/* For uniformity, we'd like to treat the CFA save-location like any - other register save-location, but this doesn't quite work, because - the CFA can be expressed as a (REGISTER,OFFSET) pair. To handle - this, we use two dwarf_save_loc structures to describe the CFA. - The first one (CFA_REG_COLUMN), tells us where the CFA is saved. - In the case of DWARF_WHERE_EXPR, the CFA is defined by a DWARF - location expression whose address is given by member "val". In the - case of DWARF_WHERE_REG, member "val" gives the number of the - base-register and the "val" member of DWARF_CFA_OFF_COLUMN gives - the offset value. */ -#define DWARF_CFA_REG_COLUMN DWARF_NUM_PRESERVED_REGS -#define DWARF_CFA_OFF_COLUMN (DWARF_NUM_PRESERVED_REGS + 1) - -typedef struct dwarf_reg_only_state - { - char where[DWARF_NUM_PRESERVED_REGS + 2]; /* how is the register saved? */ - unw_word_t val[DWARF_NUM_PRESERVED_REGS + 2]; /* where it's saved */ - } -dwarf_reg_only_state_t; - -typedef struct dwarf_reg_state - { - unw_word_t ret_addr_column; /* which column in rule table represents return address */ - dwarf_reg_only_state_t reg; - } -dwarf_reg_state_t; - -typedef struct dwarf_stackable_reg_state - { - struct dwarf_stackable_reg_state *next; /* for rs_stack */ - dwarf_reg_only_state_t state; - } -dwarf_stackable_reg_state_t; - -typedef struct dwarf_reg_cache_entry - { - unw_word_t ip; /* ip this rs is for */ - unsigned short coll_chain; /* used for hash collisions */ - unsigned short hint; /* hint for next rs to try (or -1) */ - unsigned short valid : 1; /* optional machine-dependent signal info */ - unsigned short signal_frame : 1; /* optional machine-dependent signal info */ - } -dwarf_reg_cache_entry_t; - -typedef struct dwarf_cie_info - { - unw_word_t cie_instr_start; /* start addr. of CIE "initial_instructions" */ - unw_word_t cie_instr_end; /* end addr. of CIE "initial_instructions" */ - unw_word_t fde_instr_start; /* start addr. of FDE "instructions" */ - unw_word_t fde_instr_end; /* end addr. of FDE "instructions" */ - unw_word_t code_align; /* code-alignment factor */ - unw_word_t data_align; /* data-alignment factor */ - unw_word_t ret_addr_column; /* column of return-address register */ - unw_word_t handler; /* address of personality-routine */ - uint16_t abi; - uint16_t tag; - uint8_t fde_encoding; - uint8_t lsda_encoding; - unsigned int sized_augmentation : 1; - unsigned int have_abi_marker : 1; - unsigned int signal_frame : 1; - } -dwarf_cie_info_t; - -typedef struct dwarf_state_record - { - unsigned char fde_encoding; - unw_word_t args_size; - - dwarf_reg_state_t rs_initial; /* reg-state after CIE instructions */ - dwarf_reg_state_t rs_current; /* current reg-state */ - } -dwarf_state_record_t; - -typedef struct dwarf_cursor - { - void *as_arg; /* argument to address-space callbacks */ - unw_addr_space_t as; /* reference to per-address-space info */ - - unw_word_t cfa; /* canonical frame address; aka frame-/stack-pointer */ - unw_word_t ip; /* instruction pointer */ - unw_word_t args_size; /* size of arguments */ - unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS]; - unsigned int eh_valid_mask; - - dwarf_loc_t loc[DWARF_NUM_PRESERVED_REGS]; - - unsigned int stash_frames :1; /* stash frames for fast lookup */ - unsigned int use_prev_instr :1; /* use previous (= call) or current (= signal) instruction? */ - unsigned int pi_valid :1; /* is proc_info valid? */ - unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */ - unw_proc_info_t pi; /* info about current procedure */ - - short hint; /* faster lookup of the rs cache */ - short prev_rs; - } -dwarf_cursor_t; - -#define DWARF_DEFAULT_LOG_UNW_CACHE_SIZE 7 -#define DWARF_DEFAULT_UNW_CACHE_SIZE (1 << DWARF_DEFAULT_LOG_UNW_CACHE_SIZE) - -#define DWARF_DEFAULT_LOG_UNW_HASH_SIZE (DWARF_DEFAULT_LOG_UNW_CACHE_SIZE + 1) -#define DWARF_DEFAULT_UNW_HASH_SIZE (1 << DWARF_DEFAULT_LOG_UNW_HASH_SIZE) - -typedef unsigned char unw_hash_index_t; - -struct dwarf_rs_cache - { - pthread_mutex_t lock; - unsigned short rr_head; /* index of least-recently allocated rs */ - - unsigned short log_size; - unsigned short prev_log_size; - - /* hash table that maps instruction pointer to rs index: */ - unsigned short *hash; - - uint32_t generation; /* generation number */ - - /* rs cache: */ - dwarf_reg_state_t *buckets; - dwarf_reg_cache_entry_t *links; - - /* default memory, loaded in BSS segment */ - unsigned short default_hash[DWARF_DEFAULT_UNW_HASH_SIZE]; - dwarf_reg_state_t default_buckets[DWARF_DEFAULT_UNW_CACHE_SIZE]; - dwarf_reg_cache_entry_t default_links[DWARF_DEFAULT_UNW_CACHE_SIZE]; - }; - -/* A list of descriptors for loaded .debug_frame sections. */ - -struct unw_debug_frame_list - { - /* The start (inclusive) and end (exclusive) of the described region. */ - unw_word_t start; - unw_word_t end; - /* The debug frame itself. */ - char *debug_frame; - size_t debug_frame_size; - /* Index (for binary search). */ - struct table_entry *index; - size_t index_size; - /* Pointer to next descriptor. */ - struct unw_debug_frame_list *next; - }; - -/* Convenience macros: */ -#define dwarf_init UNW_ARCH_OBJ (dwarf_init) -#define dwarf_callback UNW_OBJ (dwarf_callback) -#define dwarf_find_proc_info UNW_OBJ (dwarf_find_proc_info) -#define dwarf_find_debug_frame UNW_OBJ (dwarf_find_debug_frame) -#define dwarf_search_unwind_table UNW_OBJ (dwarf_search_unwind_table) -#define dwarf_find_unwind_table UNW_OBJ (dwarf_find_unwind_table) -#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info) -#define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info) -#define dwarf_eval_expr UNW_OBJ (dwarf_eval_expr) -#define dwarf_stack_aligned UNW_OBJ (dwarf_stack_aligned) -#define dwarf_extract_proc_info_from_fde \ - UNW_OBJ (dwarf_extract_proc_info_from_fde) -#define dwarf_find_save_locs UNW_OBJ (dwarf_find_save_locs) -#define dwarf_make_proc_info UNW_OBJ (dwarf_make_proc_info) -#define dwarf_apply_reg_state UNW_OBJ (dwarf_apply_reg_state) -#define dwarf_reg_states_iterate UNW_OBJ (dwarf_reg_states_iterate) -#define dwarf_read_encoded_pointer UNW_OBJ (dwarf_read_encoded_pointer) -#define dwarf_step UNW_OBJ (dwarf_step) -#define dwarf_flush_rs_cache UNW_OBJ (dwarf_flush_rs_cache) - -extern int dwarf_init (void); -#ifndef UNW_REMOTE_ONLY -extern int dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr); -extern int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, - int need_unwind_info, void *arg); -#endif /* !UNW_REMOTE_ONLY */ -extern int dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, - unw_word_t ip, unw_word_t segbase, - const char* obj_name, unw_word_t start, - unw_word_t end); -extern int dwarf_search_unwind_table (unw_addr_space_t as, - unw_word_t ip, - unw_dyn_info_t *di, - unw_proc_info_t *pi, - int need_unwind_info, void *arg); -extern int dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, - char *path, unw_word_t segbase, unw_word_t mapoff, - unw_word_t ip); -extern void dwarf_put_unwind_info (unw_addr_space_t as, - unw_proc_info_t *pi, void *arg); -extern int dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr, - unw_word_t len, unw_word_t *valp, - int *is_register); -extern int -dwarf_stack_aligned(struct dwarf_cursor *c, unw_word_t cfa_addr, - unw_word_t rbp_addr, unw_word_t *offset); - -extern int dwarf_extract_proc_info_from_fde (unw_addr_space_t as, - unw_accessors_t *a, - unw_word_t *fde_addr, - unw_proc_info_t *pi, - unw_word_t base, - int need_unwind_info, - int is_debug_frame, - void *arg); -extern int dwarf_find_save_locs (struct dwarf_cursor *c); -extern int dwarf_make_proc_info (struct dwarf_cursor *c); -extern int dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs); -extern int dwarf_reg_states_iterate (struct dwarf_cursor *c, unw_reg_states_callback cb, void *token); -extern int dwarf_read_encoded_pointer (unw_addr_space_t as, - unw_accessors_t *a, - unw_word_t *addr, - unsigned char encoding, - const unw_proc_info_t *pi, - unw_word_t *valp, void *arg); -extern int dwarf_step (struct dwarf_cursor *c); -extern int dwarf_flush_rs_cache (struct dwarf_rs_cache *cache); - -#endif /* dwarf_h */ diff --git a/contrib/libunwind/include/dwarf_i.h b/contrib/libunwind/include/dwarf_i.h deleted file mode 100644 index 983b9f5c2af..00000000000 --- a/contrib/libunwind/include/dwarf_i.h +++ /dev/null @@ -1,490 +0,0 @@ -#ifndef DWARF_I_H -#define DWARF_I_H - -/* This file contains definitions that cannot be used in code outside - of libunwind. In particular, most inline functions are here - because otherwise they'd generate unresolved references when the - files are compiled with inlining disabled. */ - -#include "dwarf.h" -#include "libunwind_i.h" - -/* Unless we are told otherwise, assume that a "machine address" is - the size of an unw_word_t. */ -#ifndef dwarf_addr_size -# define dwarf_addr_size(as) (sizeof (unw_word_t)) -#endif - -#ifndef dwarf_to_unw_regnum -# define dwarf_to_unw_regnum_map UNW_OBJ (dwarf_to_unw_regnum_map) -extern const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH]; -/* REG is evaluated multiple times; it better be side-effects free! */ -# define dwarf_to_unw_regnum(reg) \ - (((reg) < DWARF_REGNUM_MAP_LENGTH) ? dwarf_to_unw_regnum_map[reg] : 0) -#endif - -#ifdef UNW_LOCAL_ONLY - -/* In the local-only case, we can let the compiler directly access - memory and don't need to worry about differing byte-order. */ - -typedef union __attribute__ ((packed)) - { - int8_t s8; - int16_t s16; - int32_t s32; - int64_t s64; - uint8_t u8; - uint16_t u16; - uint32_t u32; - uint64_t u64; - void *ptr; - } -dwarf_misaligned_value_t; - -static inline int -dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - int8_t *val, void *arg) -{ - dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; - - *val = mvp->s8; - *addr += sizeof (mvp->s8); - return 0; -} - -static inline int -dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - int16_t *val, void *arg) -{ - dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; - - *val = mvp->s16; - *addr += sizeof (mvp->s16); - return 0; -} - -static inline int -dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - int32_t *val, void *arg) -{ - dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; - - *val = mvp->s32; - *addr += sizeof (mvp->s32); - return 0; -} - -static inline int -dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - int64_t *val, void *arg) -{ - dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; - - *val = mvp->s64; - *addr += sizeof (mvp->s64); - return 0; -} - -static inline int -dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - uint8_t *val, void *arg) -{ - dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; - - *val = mvp->u8; - *addr += sizeof (mvp->u8); - return 0; -} - -static inline int -dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - uint16_t *val, void *arg) -{ - dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; - - *val = mvp->u16; - *addr += sizeof (mvp->u16); - return 0; -} - -static inline int -dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - uint32_t *val, void *arg) -{ - dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; - - *val = mvp->u32; - *addr += sizeof (mvp->u32); - return 0; -} - -static inline int -dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - uint64_t *val, void *arg) -{ - dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; - - *val = mvp->u64; - *addr += sizeof (mvp->u64); - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ - -static inline int -dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - uint8_t *valp, void *arg) -{ - unw_word_t val, aligned_addr = *addr & -sizeof (unw_word_t); - unw_word_t off = *addr - aligned_addr; - int ret; - - *addr += 1; - ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); -#if __BYTE_ORDER == __LITTLE_ENDIAN - val >>= 8*off; -#else - val >>= 8*(sizeof (unw_word_t) - 1 - off); -#endif - *valp = (uint8_t) val; - return ret; -} - -static inline int -dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - uint16_t *val, void *arg) -{ - uint8_t v0, v1; - int ret; - - if ((ret = dwarf_readu8 (as, a, addr, &v0, arg)) < 0 - || (ret = dwarf_readu8 (as, a, addr, &v1, arg)) < 0) - return ret; - - if (tdep_big_endian (as)) - *val = (uint16_t) v0 << 8 | v1; - else - *val = (uint16_t) v1 << 8 | v0; - return 0; -} - -static inline int -dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - uint32_t *val, void *arg) -{ - uint16_t v0, v1; - int ret; - - if ((ret = dwarf_readu16 (as, a, addr, &v0, arg)) < 0 - || (ret = dwarf_readu16 (as, a, addr, &v1, arg)) < 0) - return ret; - - if (tdep_big_endian (as)) - *val = (uint32_t) v0 << 16 | v1; - else - *val = (uint32_t) v1 << 16 | v0; - return 0; -} - -static inline int -dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - uint64_t *val, void *arg) -{ - uint32_t v0, v1; - int ret; - - if ((ret = dwarf_readu32 (as, a, addr, &v0, arg)) < 0 - || (ret = dwarf_readu32 (as, a, addr, &v1, arg)) < 0) - return ret; - - if (tdep_big_endian (as)) - *val = (uint64_t) v0 << 32 | v1; - else - *val = (uint64_t) v1 << 32 | v0; - return 0; -} - -static inline int -dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - int8_t *val, void *arg) -{ - uint8_t uval; - int ret; - - if ((ret = dwarf_readu8 (as, a, addr, &uval, arg)) < 0) - return ret; - *val = (int8_t) uval; - return 0; -} - -static inline int -dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - int16_t *val, void *arg) -{ - uint16_t uval; - int ret; - - if ((ret = dwarf_readu16 (as, a, addr, &uval, arg)) < 0) - return ret; - *val = (int16_t) uval; - return 0; -} - -static inline int -dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - int32_t *val, void *arg) -{ - uint32_t uval; - int ret; - - if ((ret = dwarf_readu32 (as, a, addr, &uval, arg)) < 0) - return ret; - *val = (int32_t) uval; - return 0; -} - -static inline int -dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - int64_t *val, void *arg) -{ - uint64_t uval; - int ret; - - if ((ret = dwarf_readu64 (as, a, addr, &uval, arg)) < 0) - return ret; - *val = (int64_t) uval; - return 0; -} - -#endif /* !UNW_LOCAL_ONLY */ - -static inline int -dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - unw_word_t *val, void *arg) -{ - uint32_t u32; - uint64_t u64; - int ret; - - switch (dwarf_addr_size (as)) - { - case 4: - ret = dwarf_readu32 (as, a, addr, &u32, arg); - if (ret < 0) - return ret; - *val = u32; - return ret; - - case 8: - ret = dwarf_readu64 (as, a, addr, &u64, arg); - if (ret < 0) - return ret; - *val = u64; - return ret; - - default: - abort (); - } -} - -/* Read an unsigned "little-endian base 128" value. See Chapter 7.6 - of DWARF spec v3. */ - -static inline int -dwarf_read_uleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - unw_word_t *valp, void *arg) -{ - unw_word_t val = 0, shift = 0; - unsigned char byte; - int ret; - - do - { - if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0) - return ret; - - val |= ((unw_word_t) byte & 0x7f) << shift; - shift += 7; - } - while (byte & 0x80); - - *valp = val; - return 0; -} - -/* Read a signed "little-endian base 128" value. See Chapter 7.6 of - DWARF spec v3. */ - -static inline int -dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - unw_word_t *valp, void *arg) -{ - unw_word_t val = 0, shift = 0; - unsigned char byte; - int ret; - - do - { - if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0) - return ret; - - val |= ((unw_word_t) byte & 0x7f) << shift; - shift += 7; - } - while (byte & 0x80); - - if (shift < 8 * sizeof (unw_word_t) && (byte & 0x40) != 0) - /* sign-extend negative value */ - val |= ((unw_word_t) -1) << shift; - - *valp = val; - return 0; -} - -static ALWAYS_INLINE int -dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, unsigned char encoding, - const unw_proc_info_t *pi, - unw_word_t *valp, void *arg) -{ - unw_word_t val, initial_addr = *addr; - uint16_t uval16; - uint32_t uval32; - uint64_t uval64; - int16_t sval16 = 0; - int32_t sval32 = 0; - int64_t sval64 = 0; - int ret; - - /* DW_EH_PE_omit and DW_EH_PE_aligned don't follow the normal - format/application encoding. Handle them first. */ - if (encoding == DW_EH_PE_omit) - { - *valp = 0; - return 0; - } - else if (encoding == DW_EH_PE_aligned) - { - int size = dwarf_addr_size (as); - *addr = (initial_addr + size - 1) & -size; - return dwarf_readw (as, a, addr, valp, arg); - } - - switch (encoding & DW_EH_PE_FORMAT_MASK) - { - case DW_EH_PE_ptr: - if ((ret = dwarf_readw (as, a, addr, &val, arg)) < 0) - return ret; - break; - - case DW_EH_PE_uleb128: - if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) - return ret; - break; - - case DW_EH_PE_udata2: - if ((ret = dwarf_readu16 (as, a, addr, &uval16, arg)) < 0) - return ret; - val = uval16; - break; - - case DW_EH_PE_udata4: - if ((ret = dwarf_readu32 (as, a, addr, &uval32, arg)) < 0) - return ret; - val = uval32; - break; - - case DW_EH_PE_udata8: - if ((ret = dwarf_readu64 (as, a, addr, &uval64, arg)) < 0) - return ret; - val = uval64; - break; - - case DW_EH_PE_sleb128: - if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) - return ret; - break; - - case DW_EH_PE_sdata2: - if ((ret = dwarf_reads16 (as, a, addr, &sval16, arg)) < 0) - return ret; - val = sval16; - break; - - case DW_EH_PE_sdata4: - if ((ret = dwarf_reads32 (as, a, addr, &sval32, arg)) < 0) - return ret; - val = sval32; - break; - - case DW_EH_PE_sdata8: - if ((ret = dwarf_reads64 (as, a, addr, &sval64, arg)) < 0) - return ret; - val = sval64; - break; - - default: - Debug (1, "unexpected encoding format 0x%x\n", - encoding & DW_EH_PE_FORMAT_MASK); - return -UNW_EINVAL; - } - - if (val == 0) - { - /* 0 is a special value and always absolute. */ - *valp = 0; - return 0; - } - - switch (encoding & DW_EH_PE_APPL_MASK) - { - case DW_EH_PE_absptr: - break; - - case DW_EH_PE_pcrel: - val += initial_addr; - break; - - case DW_EH_PE_datarel: - /* XXX For now, assume that data-relative addresses are relative - to the global pointer. */ - val += pi->gp; - break; - - case DW_EH_PE_funcrel: - val += pi->start_ip; - break; - - case DW_EH_PE_textrel: - /* XXX For now we don't support text-rel values. If there is a - platform which needs this, we probably would have to add a - "segbase" member to unw_proc_info_t. */ - default: - Debug (1, "unexpected application type 0x%x\n", - encoding & DW_EH_PE_APPL_MASK); - return -UNW_EINVAL; - } - - /* Trim off any extra bits. Assume that sign extension isn't - required; the only place it is needed is MIPS kernel space - addresses. */ - if (sizeof (val) > dwarf_addr_size (as)) - { - assert (dwarf_addr_size (as) == 4); - val = (uint32_t) val; - } - - if (encoding & DW_EH_PE_indirect) - { - unw_word_t indirect_addr = val; - - if ((ret = dwarf_readw (as, a, &indirect_addr, &val, arg)) < 0) - return ret; - } - - *valp = val; - return 0; -} - -#endif /* DWARF_I_H */ diff --git a/contrib/libunwind/include/libunwind-aarch64.h b/contrib/libunwind/include/libunwind-aarch64.h deleted file mode 100644 index 85812e151d7..00000000000 --- a/contrib/libunwind/include/libunwind-aarch64.h +++ /dev/null @@ -1,210 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#include -#include -#include - -#define UNW_TARGET aarch64 -#define UNW_TARGET_AARCH64 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* This needs to be big enough to accommodate "struct cursor", while - leaving some slack for future expansion. Changing this value will - require recompiling all users of this library. Stack allocation is - relatively cheap and unwind-state copying is relatively rare, so we - want to err on making it rather too big than too small. */ - -#define UNW_TDEP_CURSOR_LEN 512 - -typedef uint64_t unw_word_t; -typedef int64_t unw_sword_t; - -typedef long double unw_tdep_fpreg_t; - -typedef struct - { - /* no aarch64-specific auxiliary proc-info */ - } -unw_tdep_proc_info_t; - -typedef enum - { - /* 64-bit general registers. */ - UNW_AARCH64_X0, - UNW_AARCH64_X1, - UNW_AARCH64_X2, - UNW_AARCH64_X3, - UNW_AARCH64_X4, - UNW_AARCH64_X5, - UNW_AARCH64_X6, - UNW_AARCH64_X7, - UNW_AARCH64_X8, - - /* Temporary registers. */ - UNW_AARCH64_X9, - UNW_AARCH64_X10, - UNW_AARCH64_X11, - UNW_AARCH64_X12, - UNW_AARCH64_X13, - UNW_AARCH64_X14, - UNW_AARCH64_X15, - - /* Intra-procedure-call temporary registers. */ - UNW_AARCH64_X16, - UNW_AARCH64_X17, - - /* Callee-saved registers. */ - UNW_AARCH64_X18, - UNW_AARCH64_X19, - UNW_AARCH64_X20, - UNW_AARCH64_X21, - UNW_AARCH64_X22, - UNW_AARCH64_X23, - UNW_AARCH64_X24, - UNW_AARCH64_X25, - UNW_AARCH64_X26, - UNW_AARCH64_X27, - UNW_AARCH64_X28, - - /* 64-bit frame pointer. */ - UNW_AARCH64_X29, - - /* 64-bit link register. */ - UNW_AARCH64_X30, - - /* 64-bit stack pointer. */ - UNW_AARCH64_SP = 31, - UNW_AARCH64_PC, - UNW_AARCH64_PSTATE, - - /* 128-bit FP/Advanced SIMD registers. */ - UNW_AARCH64_V0 = 64, - UNW_AARCH64_V1, - UNW_AARCH64_V2, - UNW_AARCH64_V3, - UNW_AARCH64_V4, - UNW_AARCH64_V5, - UNW_AARCH64_V6, - UNW_AARCH64_V7, - UNW_AARCH64_V8, - UNW_AARCH64_V9, - UNW_AARCH64_V10, - UNW_AARCH64_V11, - UNW_AARCH64_V12, - UNW_AARCH64_V13, - UNW_AARCH64_V14, - UNW_AARCH64_V15, - UNW_AARCH64_V16, - UNW_AARCH64_V17, - UNW_AARCH64_V18, - UNW_AARCH64_V19, - UNW_AARCH64_V20, - UNW_AARCH64_V21, - UNW_AARCH64_V22, - UNW_AARCH64_V23, - UNW_AARCH64_V24, - UNW_AARCH64_V25, - UNW_AARCH64_V26, - UNW_AARCH64_V27, - UNW_AARCH64_V28, - UNW_AARCH64_V29, - UNW_AARCH64_V30, - UNW_AARCH64_V31, - - UNW_AARCH64_FPSR, - UNW_AARCH64_FPCR, - - /* For AArch64, the CFA is the value of SP (x31) at the call site of the - previous frame. */ - UNW_AARCH64_CFA = UNW_AARCH64_SP, - - UNW_TDEP_LAST_REG = UNW_AARCH64_FPCR, - - UNW_TDEP_IP = UNW_AARCH64_X30, - UNW_TDEP_SP = UNW_AARCH64_SP, - UNW_TDEP_EH = UNW_AARCH64_X0, - - } -aarch64_regnum_t; - -/* Use R0 through R3 to pass exception handling information. */ -#define UNW_TDEP_NUM_EH_REGS 4 - -typedef struct unw_tdep_save_loc - { - /* Additional target-dependent info on a save location. */ - } -unw_tdep_save_loc_t; - - -/* On AArch64, we can directly use ucontext_t as the unwind context. */ -typedef ucontext_t unw_tdep_context_t; - -#include "libunwind-common.h" -#include "libunwind-dynamic.h" - -#define unw_tdep_getcontext(uc) (({ \ - unw_tdep_context_t *unw_ctx = (uc); \ - register uint64_t *unw_base asm ("x0") = (uint64_t*) unw_ctx->uc_mcontext.regs; \ - __asm__ __volatile__ ( \ - "stp x0, x1, [%[base], #0]\n" \ - "stp x2, x3, [%[base], #16]\n" \ - "stp x4, x5, [%[base], #32]\n" \ - "stp x6, x7, [%[base], #48]\n" \ - "stp x8, x9, [%[base], #64]\n" \ - "stp x10, x11, [%[base], #80]\n" \ - "stp x12, x13, [%[base], #96]\n" \ - "stp x14, x13, [%[base], #112]\n" \ - "stp x16, x17, [%[base], #128]\n" \ - "stp x18, x19, [%[base], #144]\n" \ - "stp x20, x21, [%[base], #160]\n" \ - "stp x22, x23, [%[base], #176]\n" \ - "stp x24, x25, [%[base], #192]\n" \ - "stp x26, x27, [%[base], #208]\n" \ - "stp x28, x29, [%[base], #224]\n" \ - "str x30, [%[base], #240]\n" \ - "mov x1, sp\n" \ - "stp x1, x30, [%[base], #248]\n" \ - : [base] "+r" (unw_base) : : "x1", "memory"); \ - }), 0) -#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) - -extern int unw_tdep_is_fpreg (int); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/contrib/libunwind/include/libunwind-arm.h b/contrib/libunwind/include/libunwind-arm.h deleted file mode 100644 index 6709b7abaee..00000000000 --- a/contrib/libunwind/include/libunwind-arm.h +++ /dev/null @@ -1,303 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#include -#include - -#define UNW_TARGET arm -#define UNW_TARGET_ARM 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* This needs to be big enough to accommodate "struct cursor", while - leaving some slack for future expansion. Changing this value will - require recompiling all users of this library. Stack allocation is - relatively cheap and unwind-state copying is relatively rare, so we - want to err on making it rather too big than too small. */ - -/* FIXME for ARM. Too big? What do other things use for similar tasks? */ -#define UNW_TDEP_CURSOR_LEN 4096 - -typedef uint32_t unw_word_t; -typedef int32_t unw_sword_t; - -typedef long double unw_tdep_fpreg_t; - -typedef enum - { - UNW_ARM_R0, - UNW_ARM_R1, - UNW_ARM_R2, - UNW_ARM_R3, - UNW_ARM_R4, - UNW_ARM_R5, - UNW_ARM_R6, - UNW_ARM_R7, - UNW_ARM_R8, - UNW_ARM_R9, - UNW_ARM_R10, - UNW_ARM_R11, - UNW_ARM_R12, - UNW_ARM_R13, - UNW_ARM_R14, - UNW_ARM_R15, - - /* VFPv2 s0-s31 (obsolescent numberings). */ - UNW_ARM_S0 = 64, - UNW_ARM_S1, - UNW_ARM_S2, - UNW_ARM_S3, - UNW_ARM_S4, - UNW_ARM_S5, - UNW_ARM_S6, - UNW_ARM_S7, - UNW_ARM_S8, - UNW_ARM_S9, - UNW_ARM_S10, - UNW_ARM_S11, - UNW_ARM_S12, - UNW_ARM_S13, - UNW_ARM_S14, - UNW_ARM_S15, - UNW_ARM_S16, - UNW_ARM_S17, - UNW_ARM_S18, - UNW_ARM_S19, - UNW_ARM_S20, - UNW_ARM_S21, - UNW_ARM_S22, - UNW_ARM_S23, - UNW_ARM_S24, - UNW_ARM_S25, - UNW_ARM_S26, - UNW_ARM_S27, - UNW_ARM_S28, - UNW_ARM_S29, - UNW_ARM_S30, - UNW_ARM_S31, - - /* FPA register numberings. */ - UNW_ARM_F0 = 96, - UNW_ARM_F1, - UNW_ARM_F2, - UNW_ARM_F3, - UNW_ARM_F4, - UNW_ARM_F5, - UNW_ARM_F6, - UNW_ARM_F7, - - /* iWMMXt GR register numberings. */ - UNW_ARM_wCGR0 = 104, - UNW_ARM_wCGR1, - UNW_ARM_wCGR2, - UNW_ARM_wCGR3, - UNW_ARM_wCGR4, - UNW_ARM_wCGR5, - UNW_ARM_wCGR6, - UNW_ARM_wCGR7, - - /* iWMMXt register numberings. */ - UNW_ARM_wR0 = 112, - UNW_ARM_wR1, - UNW_ARM_wR2, - UNW_ARM_wR3, - UNW_ARM_wR4, - UNW_ARM_wR5, - UNW_ARM_wR6, - UNW_ARM_wR7, - UNW_ARM_wR8, - UNW_ARM_wR9, - UNW_ARM_wR10, - UNW_ARM_wR11, - UNW_ARM_wR12, - UNW_ARM_wR13, - UNW_ARM_wR14, - UNW_ARM_wR15, - - /* Two-byte encodings from here on. */ - - /* SPSR. */ - UNW_ARM_SPSR = 128, - UNW_ARM_SPSR_FIQ, - UNW_ARM_SPSR_IRQ, - UNW_ARM_SPSR_ABT, - UNW_ARM_SPSR_UND, - UNW_ARM_SPSR_SVC, - - /* User mode registers. */ - UNW_ARM_R8_USR = 144, - UNW_ARM_R9_USR, - UNW_ARM_R10_USR, - UNW_ARM_R11_USR, - UNW_ARM_R12_USR, - UNW_ARM_R13_USR, - UNW_ARM_R14_USR, - - /* FIQ registers. */ - UNW_ARM_R8_FIQ = 151, - UNW_ARM_R9_FIQ, - UNW_ARM_R10_FIQ, - UNW_ARM_R11_FIQ, - UNW_ARM_R12_FIQ, - UNW_ARM_R13_FIQ, - UNW_ARM_R14_FIQ, - - /* IRQ registers. */ - UNW_ARM_R13_IRQ = 158, - UNW_ARM_R14_IRQ, - - /* ABT registers. */ - UNW_ARM_R13_ABT = 160, - UNW_ARM_R14_ABT, - - /* UND registers. */ - UNW_ARM_R13_UND = 162, - UNW_ARM_R14_UND, - - /* SVC registers. */ - UNW_ARM_R13_SVC = 164, - UNW_ARM_R14_SVC, - - /* iWMMXt control registers. */ - UNW_ARM_wC0 = 192, - UNW_ARM_wC1, - UNW_ARM_wC2, - UNW_ARM_wC3, - UNW_ARM_wC4, - UNW_ARM_wC5, - UNW_ARM_wC6, - UNW_ARM_wC7, - - /* VFPv3/Neon 64-bit registers. */ - UNW_ARM_D0 = 256, - UNW_ARM_D1, - UNW_ARM_D2, - UNW_ARM_D3, - UNW_ARM_D4, - UNW_ARM_D5, - UNW_ARM_D6, - UNW_ARM_D7, - UNW_ARM_D8, - UNW_ARM_D9, - UNW_ARM_D10, - UNW_ARM_D11, - UNW_ARM_D12, - UNW_ARM_D13, - UNW_ARM_D14, - UNW_ARM_D15, - UNW_ARM_D16, - UNW_ARM_D17, - UNW_ARM_D18, - UNW_ARM_D19, - UNW_ARM_D20, - UNW_ARM_D21, - UNW_ARM_D22, - UNW_ARM_D23, - UNW_ARM_D24, - UNW_ARM_D25, - UNW_ARM_D26, - UNW_ARM_D27, - UNW_ARM_D28, - UNW_ARM_D29, - UNW_ARM_D30, - UNW_ARM_D31, - - /* For ARM, the CFA is the value of SP (r13) at the call site in the - previous frame. */ - UNW_ARM_CFA, - - UNW_TDEP_LAST_REG = UNW_ARM_D31, - - UNW_TDEP_IP = UNW_ARM_R14, /* A little white lie. */ - UNW_TDEP_SP = UNW_ARM_R13, - UNW_TDEP_EH = UNW_ARM_R0 /* FIXME. */ - } -arm_regnum_t; - -#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for ARM. */ - -typedef struct unw_tdep_save_loc - { - /* Additional target-dependent info on a save location. */ - } -unw_tdep_save_loc_t; - -/* On ARM, we define our own unw_tdep_context instead of using ucontext_t. - This allows us to support systems that don't support getcontext and - therefore do not define ucontext_t. */ -typedef struct unw_tdep_context - { - unsigned long regs[16]; - } -unw_tdep_context_t; - -/* There is no getcontext() on ARM. Use a stub version which only saves GP - registers. FIXME: Not ideal, may not be sufficient for all libunwind - use cases. Stores pc+8, which is only approximately correct, really. */ -#ifndef __thumb__ -#define unw_tdep_getcontext(uc) (({ \ - unw_tdep_context_t *unw_ctx = (uc); \ - register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs; \ - __asm__ __volatile__ ( \ - "stmia %[base], {r0-r15}" \ - : : [base] "r" (unw_base) : "memory"); \ - }), 0) -#else /* __thumb__ */ -#define unw_tdep_getcontext(uc) (({ \ - unw_tdep_context_t *unw_ctx = (uc); \ - register unsigned long *unw_base __asm__ ("r0") = unw_ctx->regs; \ - __asm__ __volatile__ ( \ - ".align 2\nbx pc\nnop\n.code 32\n" \ - "stmia %[base], {r0-r15}\n" \ - "orr %[base], pc, #1\nbx %[base]\n" \ - ".code 16\n" \ - : [base] "+r" (unw_base) : : "memory", "cc"); \ - }), 0) -#endif - -#include "libunwind-dynamic.h" - -typedef struct - { - /* no arm-specific auxiliary proc-info */ - } -unw_tdep_proc_info_t; - -#include "libunwind-common.h" - -#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) -extern int unw_tdep_is_fpreg (int); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/contrib/libunwind/include/libunwind-common.h.in b/contrib/libunwind/include/libunwind-common.h.in deleted file mode 100644 index 9811f4915e6..00000000000 --- a/contrib/libunwind/include/libunwind-common.h.in +++ /dev/null @@ -1,279 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#define UNW_VERSION_MAJOR @PKG_MAJOR@ -#define UNW_VERSION_MINOR @PKG_MINOR@ -#define UNW_VERSION_EXTRA @PKG_EXTRA@ - -#define UNW_VERSION_CODE(maj,min) (((maj) << 16) | (min)) -#define UNW_VERSION UNW_VERSION_CODE(UNW_VERSION_MAJOR, UNW_VERSION_MINOR) - -#define UNW_PASTE2(x,y) x##y -#define UNW_PASTE(x,y) UNW_PASTE2(x,y) -#define UNW_OBJ(fn) UNW_PASTE(UNW_PREFIX, fn) -#define UNW_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_), fn) - -#ifdef UNW_LOCAL_ONLY -# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_UL,UNW_TARGET),_) -#else /* !UNW_LOCAL_ONLY */ -# define UNW_PREFIX UNW_PASTE(UNW_PASTE(_U,UNW_TARGET),_) -#endif /* !UNW_LOCAL_ONLY */ - -/* Error codes. The unwind routines return the *negated* values of - these error codes on error and a non-negative value on success. */ -typedef enum - { - UNW_ESUCCESS = 0, /* no error */ - UNW_EUNSPEC, /* unspecified (general) error */ - UNW_ENOMEM, /* out of memory */ - UNW_EBADREG, /* bad register number */ - UNW_EREADONLYREG, /* attempt to write read-only register */ - UNW_ESTOPUNWIND, /* stop unwinding */ - UNW_EINVALIDIP, /* invalid IP */ - UNW_EBADFRAME, /* bad frame */ - UNW_EINVAL, /* unsupported operation or bad value */ - UNW_EBADVERSION, /* unwind info has unsupported version */ - UNW_ENOINFO /* no unwind info found */ - } -unw_error_t; - -/* The following enum defines the indices for a couple of - (pseudo-)registers which have the same meaning across all - platforms. (RO) means read-only. (RW) means read-write. General - registers (aka "integer registers") are expected to start with - index 0. The number of such registers is architecture-dependent. - The remaining indices can be used as an architecture sees fit. The - last valid register index is given by UNW_REG_LAST. */ -typedef enum - { - UNW_REG_IP = UNW_TDEP_IP, /* (rw) instruction pointer (pc) */ - UNW_REG_SP = UNW_TDEP_SP, /* (ro) stack pointer */ - UNW_REG_EH = UNW_TDEP_EH, /* (rw) exception-handling reg base */ - UNW_REG_LAST = UNW_TDEP_LAST_REG - } -unw_frame_regnum_t; - -/* Number of exception-handler argument registers: */ -#define UNW_NUM_EH_REGS UNW_TDEP_NUM_EH_REGS - -typedef enum - { - UNW_CACHE_NONE, /* no caching */ - UNW_CACHE_GLOBAL, /* shared global cache */ - UNW_CACHE_PER_THREAD /* per-thread caching */ - } -unw_caching_policy_t; - -typedef enum - { - UNW_INIT_SIGNAL_FRAME = 1, /* We know this is a signal frame */ - } -unw_init_local2_flags_t; - -typedef int unw_regnum_t; - -/* The unwind cursor starts at the youngest (most deeply nested) frame - and is used to track the frame state as the unwinder steps from - frame to frame. It is safe to make (shallow) copies of variables - of this type. */ -typedef struct unw_cursor - { - unw_word_t opaque[UNW_TDEP_CURSOR_LEN]; - } -unw_cursor_t; - -/* This type encapsulates the entire (preserved) machine-state. */ -typedef unw_tdep_context_t unw_context_t; - -/* unw_getcontext() fills the unw_context_t pointed to by UC with the - machine state as it exists at the call-site. For implementation - reasons, this needs to be a target-dependent macro. It's easiest - to think of unw_getcontext() as being identical to getcontext(). */ -#define unw_getcontext(uc) unw_tdep_getcontext(uc) - -/* Return 1 if register number R is a floating-point register, zero - otherwise. - This routine is signal-safe. */ -#define unw_is_fpreg(r) unw_tdep_is_fpreg(r) - -typedef unw_tdep_fpreg_t unw_fpreg_t; - -typedef struct unw_addr_space *unw_addr_space_t; - -/* Each target may define it's own set of flags, but bits 0-15 are - reserved for general libunwind-use. */ -#define UNW_PI_FLAG_FIRST_TDEP_BIT 16 -/* The information comes from a .debug_frame section. */ -#define UNW_PI_FLAG_DEBUG_FRAME 32 - -typedef struct unw_proc_info - { - unw_word_t start_ip; /* first IP covered by this procedure */ - unw_word_t end_ip; /* first IP NOT covered by this procedure */ -#if defined(NEED_LAST_IP) - unw_word_t last_ip; /* first IP that could begin another procedure */ -#endif - unw_word_t lsda; /* address of lang.-spec. data area (if any) */ - unw_word_t handler; /* optional personality routine */ - unw_word_t gp; /* global-pointer value for this procedure */ - unw_word_t flags; /* misc. flags */ - - int format; /* unwind-info format (arch-specific) */ - int unwind_info_size; /* size of the information (if applicable) */ - void *unwind_info; /* unwind-info (arch-specific) */ - unw_tdep_proc_info_t extra; /* target-dependent auxiliary proc-info */ - } -unw_proc_info_t; - -typedef int (*unw_reg_states_callback)(void *token, - void *reg_states_data, - size_t reg_states_data_size, - unw_word_t start_ip, unw_word_t end_ip); - -/* These are backend callback routines that provide access to the - state of a "remote" process. This can be used, for example, to - unwind another process through the ptrace() interface. */ -typedef struct unw_accessors - { - /* Look up the unwind info associated with instruction-pointer IP. - On success, the routine fills in the PROC_INFO structure. */ - int (*find_proc_info) (unw_addr_space_t, unw_word_t, unw_proc_info_t *, - int, void *); - - /* Release any resources (e.g., memory) that were allocated for - the unwind info returned in by a previous call to - find_proc_info() with NEED_UNWIND_INFO set to 1. */ - void (*put_unwind_info) (unw_addr_space_t, unw_proc_info_t *, void *); - - /* Return the list-head of the dynamically registered unwind - info. */ - int (*get_dyn_info_list_addr) (unw_addr_space_t, unw_word_t *, void *); - - /* Access aligned word at address ADDR. The value is returned - according to the endianness of the host (e.g., if the host is - little-endian and the target is big-endian, access_mem() needs - to byte-swap the value before returning it). */ - int (*access_mem) (unw_addr_space_t, unw_word_t, unw_word_t *, int, - void *); - - /* Access register number REG at address ADDR. */ - int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, int, - void *); - - /* Access register number REG at address ADDR. */ - int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, - unw_fpreg_t *, int, void *); - - int (*resume) (unw_addr_space_t, unw_cursor_t *, void *); - - /* Optional call back to obtain the name of a (static) procedure. - Dynamically generated procedures are handled automatically by - libunwind. This callback is optional and may be set to - NULL. */ - int (*get_proc_name) (unw_addr_space_t, unw_word_t, char *, size_t, - unw_word_t *, void *); - } -unw_accessors_t; - -typedef enum unw_save_loc_type - { - UNW_SLT_NONE, /* register is not saved ("not an l-value") */ - UNW_SLT_MEMORY, /* register has been saved in memory */ - UNW_SLT_REG /* register has been saved in (another) register */ - } -unw_save_loc_type_t; - -typedef struct unw_save_loc - { - unw_save_loc_type_t type; - union - { - unw_word_t addr; /* valid if type==UNW_SLT_MEMORY */ - unw_regnum_t regnum; /* valid if type==UNW_SLT_REG */ - } - u; - unw_tdep_save_loc_t extra; /* target-dependent additional information */ - } -unw_save_loc_t; - -/* These routines work both for local and remote unwinding. */ - -#define unw_local_addr_space UNW_OBJ(local_addr_space) -#define unw_create_addr_space UNW_OBJ(create_addr_space) -#define unw_destroy_addr_space UNW_OBJ(destroy_addr_space) -#define unw_get_accessors UNW_ARCH_OBJ(get_accessors) -#define unw_init_local UNW_OBJ(init_local) -#define unw_init_local2 UNW_OBJ(init_local2) -#define unw_init_remote UNW_OBJ(init_remote) -#define unw_step UNW_OBJ(step) -#define unw_resume UNW_OBJ(resume) -#define unw_get_proc_info UNW_OBJ(get_proc_info) -#define unw_get_proc_info_by_ip UNW_OBJ(get_proc_info_by_ip) -#define unw_reg_states_iterate UNW_OBJ(reg_states_iterate) -#define unw_apply_reg_state UNW_OBJ(apply_reg_state) -#define unw_get_reg UNW_OBJ(get_reg) -#define unw_set_reg UNW_OBJ(set_reg) -#define unw_get_fpreg UNW_OBJ(get_fpreg) -#define unw_set_fpreg UNW_OBJ(set_fpreg) -#define unw_get_save_loc UNW_OBJ(get_save_loc) -#define unw_is_signal_frame UNW_OBJ(is_signal_frame) -#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame) -#define unw_get_proc_name UNW_OBJ(get_proc_name) -#define unw_set_caching_policy UNW_OBJ(set_caching_policy) -#define unw_set_cache_size UNW_OBJ(set_cache_size) -#define unw_regname UNW_ARCH_OBJ(regname) -#define unw_flush_cache UNW_ARCH_OBJ(flush_cache) -#define unw_strerror UNW_ARCH_OBJ(strerror) - -extern unw_addr_space_t unw_create_addr_space (unw_accessors_t *, int); -extern void unw_destroy_addr_space (unw_addr_space_t); -extern unw_accessors_t *unw_get_accessors (unw_addr_space_t); -extern void unw_flush_cache (unw_addr_space_t, unw_word_t, unw_word_t); -extern int unw_set_caching_policy (unw_addr_space_t, unw_caching_policy_t); -extern int unw_set_cache_size (unw_addr_space_t, size_t, int); -extern const char *unw_regname (unw_regnum_t); - -extern int unw_init_local (unw_cursor_t *, unw_context_t *); -extern int unw_init_local2 (unw_cursor_t *, unw_context_t *, int); -extern int unw_init_remote (unw_cursor_t *, unw_addr_space_t, void *); -extern int unw_step (unw_cursor_t *); -extern int unw_resume (unw_cursor_t *); -extern int unw_get_proc_info (unw_cursor_t *, unw_proc_info_t *); -extern int unw_get_proc_info_by_ip (unw_addr_space_t, unw_word_t, - unw_proc_info_t *, void *); -extern int unw_reg_states_iterate (unw_cursor_t *, unw_reg_states_callback, void *); -extern int unw_apply_reg_state (unw_cursor_t *, void *); -extern int unw_get_reg (unw_cursor_t *, int, unw_word_t *); -extern int unw_set_reg (unw_cursor_t *, int, unw_word_t); -extern int unw_get_fpreg (unw_cursor_t *, int, unw_fpreg_t *); -extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t); -extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *); -extern int unw_is_signal_frame (unw_cursor_t *); -extern int unw_handle_signal_frame (unw_cursor_t *); -extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *); -extern const char *unw_strerror (int); -extern int unw_backtrace (void **, int); - -extern unw_addr_space_t unw_local_addr_space; diff --git a/contrib/libunwind/include/libunwind-coredump.h b/contrib/libunwind/include/libunwind-coredump.h deleted file mode 100644 index 3c7814140f9..00000000000 --- a/contrib/libunwind/include/libunwind-coredump.h +++ /dev/null @@ -1,73 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef libunwind_coredump_h -#define libunwind_coredump_h - -#include - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -/* Helper routines which make it easy to use libunwind on a coredump. - They're available only if UNW_REMOTE_ONLY is _not_ defined and they - aren't really part of the libunwind API. They are implemented in a - archive library called libunwind-coredump.a. */ - -struct UCD_info; - -extern struct UCD_info *_UCD_create(const char *filename); -extern void _UCD_destroy(struct UCD_info *); - -extern int _UCD_get_num_threads(struct UCD_info *); -extern void _UCD_select_thread(struct UCD_info *, int); -extern pid_t _UCD_get_pid(struct UCD_info *); -extern int _UCD_get_cursig(struct UCD_info *); -extern int _UCD_add_backing_file_at_segment(struct UCD_info *, int phdr_no, const char *filename); -extern int _UCD_add_backing_file_at_vaddr(struct UCD_info *, - unsigned long vaddr, - const char *filename); - -extern int _UCD_find_proc_info (unw_addr_space_t, unw_word_t, - unw_proc_info_t *, int, void *); -extern void _UCD_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *); -extern int _UCD_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *, - void *); -extern int _UCD_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int, - void *); -extern int _UCD_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *, - int, void *); -extern int _UCD_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, - int, void *); -extern int _UCD_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t, - unw_word_t *, void *); -extern int _UCD_resume (unw_addr_space_t, unw_cursor_t *, void *); -extern unw_accessors_t _UCD_accessors; - - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* libunwind_coredump_h */ diff --git a/contrib/libunwind/include/libunwind-dynamic.h b/contrib/libunwind/include/libunwind-dynamic.h deleted file mode 100644 index edb0bbd343d..00000000000 --- a/contrib/libunwind/include/libunwind-dynamic.h +++ /dev/null @@ -1,214 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* This file defines the runtime-support routines for dynamically -generated code. Even though it is implemented as part of libunwind, -it is logically separate from the interface to perform the actual -unwinding. In particular, this interface is always used in the -context of the unwind target, whereas the rest of the unwind API is -used in context of the process that is doing the unwind (which may be -a debugger running on another machine, for example). - -Note that the data-structures declared here server a dual purpose: -when a program registers a dynamically generated procedure, it uses -these structures directly. On the other hand, with remote-unwinding, -the data-structures are read from the remote process's memory and -translated into internalized versions. To facilitate remote-access, -the following rules should be followed in declaring these structures: - - (1) Declare a member as a pointer only if the the information the - member points to needs to be internalized as well (e.g., a - string representing a procedure name should be declared as - "const char *", but the instruction pointer should be declared - as unw_word_t). - - (2) Provide sufficient padding to ensure that no implicit padding - will be needed on any of the supported target architectures. For - the time being, padding data structures with the assumption that - sizeof (unw_word_t) == 8 should be sufficient. (Note: it's not - impossible to internalize structures with internal padding, but - it does make the process a bit harder). - - (3) Don't declare members that contain bitfields or floating-point - values. - - (4) Don't declare members with enumeration types. Declare them as - int32_t instead. */ - -typedef enum - { - UNW_DYN_STOP = 0, /* end-of-unwind-info marker */ - UNW_DYN_SAVE_REG, /* save register to another register */ - UNW_DYN_SPILL_FP_REL, /* frame-pointer-relative register spill */ - UNW_DYN_SPILL_SP_REL, /* stack-pointer-relative register spill */ - UNW_DYN_ADD, /* add constant value to a register */ - UNW_DYN_POP_FRAMES, /* drop one or more stack frames */ - UNW_DYN_LABEL_STATE, /* name the current state */ - UNW_DYN_COPY_STATE, /* set the region's entry-state */ - UNW_DYN_ALIAS /* get unwind info from an alias */ - } -unw_dyn_operation_t; - -typedef enum - { - UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */ - UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */ - UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */ - UNW_INFO_FORMAT_ARM_EXIDX, /* ARM specific unwind info */ - UNW_INFO_FORMAT_IP_OFFSET, /* Like UNW_INFO_FORMAT_REMOTE_TABLE, but - table entries are considered - relative to di->start_ip, rather - than di->segbase */ - } -unw_dyn_info_format_t; - -typedef struct unw_dyn_op - { - int8_t tag; /* what operation? */ - int8_t qp; /* qualifying predicate register */ - int16_t reg; /* what register */ - int32_t when; /* when does it take effect? */ - unw_word_t val; /* auxiliary value */ - } -unw_dyn_op_t; - -typedef struct unw_dyn_region_info - { - struct unw_dyn_region_info *next; /* linked list of regions */ - int32_t insn_count; /* region length (# of instructions) */ - uint32_t op_count; /* length of op-array */ - unw_dyn_op_t op[1]; /* variable-length op-array */ - } -unw_dyn_region_info_t; - -typedef struct unw_dyn_proc_info - { - unw_word_t name_ptr; /* address of human-readable procedure name */ - unw_word_t handler; /* address of personality routine */ - uint32_t flags; - int32_t pad0; - unw_dyn_region_info_t *regions; - } -unw_dyn_proc_info_t; - -typedef struct unw_dyn_table_info - { - unw_word_t name_ptr; /* addr. of table name (e.g., library name) */ - unw_word_t segbase; /* segment base */ - unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */ - unw_word_t *table_data; - } -unw_dyn_table_info_t; - -typedef struct unw_dyn_remote_table_info - { - unw_word_t name_ptr; /* addr. of table name (e.g., library name) */ - unw_word_t segbase; /* segment base */ - unw_word_t table_len; /* must be a multiple of sizeof(unw_word_t)! */ - unw_word_t table_data; - } -unw_dyn_remote_table_info_t; - -typedef struct unw_dyn_info - { - /* doubly-linked list of dyn-info structures: */ - struct unw_dyn_info *next; - struct unw_dyn_info *prev; - unw_word_t start_ip; /* first IP covered by this entry */ - unw_word_t end_ip; /* first IP NOT covered by this entry */ - unw_word_t gp; /* global-pointer in effect for this entry */ - int32_t format; /* real type: unw_dyn_info_format_t */ - int32_t pad; - union - { - unw_dyn_proc_info_t pi; - unw_dyn_table_info_t ti; - unw_dyn_remote_table_info_t rti; - } - u; - } -unw_dyn_info_t; - -typedef struct unw_dyn_info_list - { - uint32_t version; - uint32_t generation; - unw_dyn_info_t *first; - } -unw_dyn_info_list_t; - -/* Return the size (in bytes) of an unw_dyn_region_info_t structure that can - hold OP_COUNT ops. */ -#define _U_dyn_region_info_size(op_count) \ - ((char *) (((unw_dyn_region_info_t *) NULL)->op + (op_count)) \ - - (char *) NULL) - -/* Register the unwind info for a single procedure. - This routine is NOT signal-safe. */ -extern void _U_dyn_register (unw_dyn_info_t *); - -/* Cancel the unwind info for a single procedure. - This routine is NOT signal-safe. */ -extern void _U_dyn_cancel (unw_dyn_info_t *); - - -/* Convenience routines. */ - -#define _U_dyn_op(_tag, _qp, _when, _reg, _val) \ - ((unw_dyn_op_t) { (_tag), (_qp), (_reg), (_when), (_val) }) - -#define _U_dyn_op_save_reg(op, qp, when, reg, dst) \ - (*(op) = _U_dyn_op (UNW_DYN_SAVE_REG, (qp), (when), (reg), (dst))) - -#define _U_dyn_op_spill_fp_rel(op, qp, when, reg, offset) \ - (*(op) = _U_dyn_op (UNW_DYN_SPILL_FP_REL, (qp), (when), (reg), \ - (offset))) - -#define _U_dyn_op_spill_sp_rel(op, qp, when, reg, offset) \ - (*(op) = _U_dyn_op (UNW_DYN_SPILL_SP_REL, (qp), (when), (reg), \ - (offset))) - -#define _U_dyn_op_add(op, qp, when, reg, value) \ - (*(op) = _U_dyn_op (UNW_DYN_ADD, (qp), (when), (reg), (value))) - -#define _U_dyn_op_pop_frames(op, qp, when, num_frames) \ - (*(op) = _U_dyn_op (UNW_DYN_POP_FRAMES, (qp), (when), 0, (num_frames))) - -#define _U_dyn_op_label_state(op, label) \ - (*(op) = _U_dyn_op (UNW_DYN_LABEL_STATE, _U_QP_TRUE, -1, 0, (label))) - -#define _U_dyn_op_copy_state(op, label) \ - (*(op) = _U_dyn_op (UNW_DYN_COPY_STATE, _U_QP_TRUE, -1, 0, (label))) - -#define _U_dyn_op_alias(op, qp, when, addr) \ - (*(op) = _U_dyn_op (UNW_DYN_ALIAS, (qp), (when), 0, (addr))) - -#define _U_dyn_op_stop(op) \ - (*(op) = _U_dyn_op (UNW_DYN_STOP, _U_QP_TRUE, -1, 0, 0)) - -/* The target-dependent qualifying predicate which is always TRUE. On - IA-64, that's p0 (0), on non-predicated architectures, the value is - ignored. */ -#define _U_QP_TRUE _U_TDEP_QP_TRUE diff --git a/contrib/libunwind/include/libunwind-hppa.h b/contrib/libunwind/include/libunwind-hppa.h deleted file mode 100644 index 7013aa77268..00000000000 --- a/contrib/libunwind/include/libunwind-hppa.h +++ /dev/null @@ -1,125 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#include -#include - -#define UNW_TARGET hppa -#define UNW_TARGET_HPPA 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* This needs to be big enough to accommodate "struct cursor", while - leaving some slack for future expansion. Changing this value will - require recompiling all users of this library. Stack allocation is - relatively cheap and unwind-state copying is relatively rare, so we - want to err on making it rather too big than too small. */ -#define UNW_TDEP_CURSOR_LEN 511 - -typedef uint32_t unw_word_t; -typedef int32_t unw_sword_t; - -typedef union - { - struct { unw_word_t bits[2]; } raw; - double val; - } -unw_tdep_fpreg_t; - -typedef enum - { - /* Note: general registers are expected to start with index 0. - This convention facilitates architecture-independent - implementation of the C++ exception handling ABI. See - _Unwind_SetGR() and _Unwind_GetGR() for details. */ - UNW_HPPA_GR = 0, - UNW_HPPA_RP = 2, /* return pointer */ - UNW_HPPA_FP = 3, /* frame pointer */ - UNW_HPPA_SP = UNW_HPPA_GR + 30, - - UNW_HPPA_FR = UNW_HPPA_GR + 32, - - UNW_HPPA_IP = UNW_HPPA_FR + 32, /* instruction pointer */ - - /* other "preserved" registers (fpsr etc.)... */ - - /* PA-RISC has 4 exception-argument registers but they're not - contiguous. To deal with this, we define 4 pseudo - exception-handling registers which we then alias to the actual - physical register. */ - - UNW_HPPA_EH0 = UNW_HPPA_IP + 1, /* alias for UNW_HPPA_GR + 20 */ - UNW_HPPA_EH1 = UNW_HPPA_EH0 + 1, /* alias for UNW_HPPA_GR + 21 */ - UNW_HPPA_EH2 = UNW_HPPA_EH1 + 1, /* alias for UNW_HPPA_GR + 22 */ - UNW_HPPA_EH3 = UNW_HPPA_EH2 + 1, /* alias for UNW_HPPA_GR + 31 */ - - /* frame info (read-only) */ - UNW_HPPA_CFA, - - UNW_TDEP_LAST_REG = UNW_HPPA_IP, - - UNW_TDEP_IP = UNW_HPPA_IP, - UNW_TDEP_SP = UNW_HPPA_SP, - UNW_TDEP_EH = UNW_HPPA_EH0 - } -hppa_regnum_t; - -#define UNW_TDEP_NUM_EH_REGS 4 - -typedef struct unw_tdep_save_loc - { - /* Additional target-dependent info on a save location. */ - } -unw_tdep_save_loc_t; - -/* On PA-RISC, we can directly use ucontext_t as the unwind context. */ -typedef ucontext_t unw_tdep_context_t; - -#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_HPPA_FR) < 32) - -#include "libunwind-dynamic.h" - -typedef struct - { - /* no PA-RISC-specific auxiliary proc-info */ - } -unw_tdep_proc_info_t; - -#include "libunwind-common.h" - -#define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext) -extern int unw_tdep_getcontext (unw_tdep_context_t *); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/contrib/libunwind/include/libunwind-ia64.h b/contrib/libunwind/include/libunwind-ia64.h deleted file mode 100644 index 0cc4f39eaab..00000000000 --- a/contrib/libunwind/include/libunwind-ia64.h +++ /dev/null @@ -1,194 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#include -#include - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#ifdef ia64 - /* This works around a bug in Intel's ECC v7.0 which defines "ia64" - as "1". */ -# undef ia64 -#endif - -#ifdef __hpux - /* On HP-UX, there is no hope of supporting UNW_LOCAL_ONLY, because - it's impossible to obtain the address of the members in the - sigcontext structure. */ -# undef UNW_LOCAL_ONLY -# define UNW_GENERIC_ONLY -#endif - -#define UNW_TARGET ia64 -#define UNW_TARGET_IA64 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* This needs to be big enough to accommodate "struct cursor", while - leaving some slack for future expansion. Changing this value will - require recompiling all users of this library. Stack allocation is - relatively cheap and unwind-state copying is relatively rare, so we - want to err on making it rather too big than too small. */ -#define UNW_TDEP_CURSOR_LEN 511 - -/* If this bit is it indicates that the procedure saved all of ar.bsp, - ar.bspstore, and ar.rnat. If, additionally, ar.bsp != saved ar.bsp, - then this procedure has performed a register-backing-store switch. */ -#define UNW_PI_FLAG_IA64_RBS_SWITCH_BIT (UNW_PI_FLAG_FIRST_TDEP_BIT + 0) - -#define UNW_PI_FLAG_IA64_RBS_SWITCH (1 << UNW_PI_FLAG_IA64_RBS_SWITCH_BIT) - -typedef uint64_t unw_word_t; -typedef int64_t unw_sword_t; - -/* On IA-64, we want to access the contents of floating-point - registers as a pair of "words", but to ensure 16-byte alignment, we - make it a union that contains a "long double". This will do the - Right Thing on all known IA-64 platforms, including HP-UX. */ -typedef union - { - struct { unw_word_t bits[2]; } raw; - long double dummy; /* dummy to force 16-byte alignment */ - } -unw_tdep_fpreg_t; - -typedef struct - { - /* no ia64-specific auxiliary proc-info */ - } -unw_tdep_proc_info_t; - -typedef enum - { - /* Note: general registers are excepted to start with index 0. - This convention facilitates architecture-independent - implementation of the C++ exception handling ABI. See - _Unwind_SetGR() and _Unwind_GetGR() for details. */ - UNW_IA64_GR = 0, /* general registers (r0..r127) */ - UNW_IA64_GP = UNW_IA64_GR + 1, - UNW_IA64_TP = UNW_IA64_GR + 13, - - UNW_IA64_NAT = UNW_IA64_GR + 128, /* NaT registers (nat0..nat127) */ - - UNW_IA64_FR = UNW_IA64_NAT + 128, /* fp registers (f0..f127) */ - - UNW_IA64_AR = UNW_IA64_FR + 128, /* application registers (ar0..r127) */ - UNW_IA64_AR_RSC = UNW_IA64_AR + 16, - UNW_IA64_AR_BSP = UNW_IA64_AR + 17, - UNW_IA64_AR_BSPSTORE = UNW_IA64_AR + 18, - UNW_IA64_AR_RNAT = UNW_IA64_AR + 19, - UNW_IA64_AR_CSD = UNW_IA64_AR + 25, - UNW_IA64_AR_26 = UNW_IA64_AR + 26, - UNW_IA64_AR_SSD = UNW_IA64_AR_26, - UNW_IA64_AR_CCV = UNW_IA64_AR + 32, - UNW_IA64_AR_UNAT = UNW_IA64_AR + 36, - UNW_IA64_AR_FPSR = UNW_IA64_AR + 40, - UNW_IA64_AR_PFS = UNW_IA64_AR + 64, - UNW_IA64_AR_LC = UNW_IA64_AR + 65, - UNW_IA64_AR_EC = UNW_IA64_AR + 66, - - UNW_IA64_BR = UNW_IA64_AR + 128, /* branch registers (b0..p7) */ - UNW_IA64_RP = UNW_IA64_BR + 0, /* return pointer (rp) */ - UNW_IA64_PR = UNW_IA64_BR + 8, /* predicate registers (p0..p63) */ - UNW_IA64_CFM, - - /* frame info: */ - UNW_IA64_BSP, - UNW_IA64_IP, - UNW_IA64_SP, - - UNW_TDEP_LAST_REG = UNW_IA64_SP, - - UNW_TDEP_IP = UNW_IA64_IP, - UNW_TDEP_SP = UNW_IA64_SP, - UNW_TDEP_EH = UNW_IA64_GR + 15 - } -ia64_regnum_t; - -#define UNW_TDEP_NUM_EH_REGS 4 /* r15-r18 are exception args */ - -typedef struct unw_tdep_save_loc - { - /* Additional target-dependent info on a save location. On IA-64, - we use this to provide the bit number in which a NaT bit gets - saved. */ - uint8_t nat_bitnr; - - /* Padding reserved for future use. */ - uint8_t reserved[7]; - } -unw_tdep_save_loc_t; - -/* On IA-64, we can directly use ucontext_t as the unwind context. */ -typedef ucontext_t unw_tdep_context_t; - -#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_IA64_FR) < 128) - -#include "libunwind-dynamic.h" -#include "libunwind-common.h" - -#ifdef __hpux - /* In theory, we could use _Uia64_getcontext() on HP-UX as well, but - the benefit of doing so would be marginal given that it can't - support UNW_LOCAL_ONLY. */ -# define unw_tdep_getcontext getcontext -#else -# define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext) - extern int unw_tdep_getcontext (unw_tdep_context_t *); -#endif - -/* This is a helper routine to search an ia64 unwind table. If the - address-space argument AS points to something other than the local - address-space, the memory for the unwind-info will be allocated - with malloc(), and should be free()d during the put_unwind_info() - callback. This routine is signal-safe for the local-address-space - case ONLY. */ -#define unw_search_ia64_unwind_table UNW_OBJ(search_unwind_table) -extern int unw_search_ia64_unwind_table (unw_addr_space_t, unw_word_t, - unw_dyn_info_t *, unw_proc_info_t *, - int, void *); - -/* This is a helper routine which the get_dyn_info_list_addr() - callback can use to locate the special dynamic-info list entry in - an IA-64 unwind table. If the entry exists in the table, the - list-address is returned. In all other cases, 0 is returned. */ -extern unw_word_t _Uia64_find_dyn_list (unw_addr_space_t, unw_dyn_info_t *, - void *); - -/* This is a helper routine to obtain the kernel-unwind info. It is - signal-safe. */ -extern int _Uia64_get_kernel_table (unw_dyn_info_t *); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/contrib/libunwind/include/libunwind-mips.h b/contrib/libunwind/include/libunwind-mips.h deleted file mode 100644 index 97c95e2463a..00000000000 --- a/contrib/libunwind/include/libunwind-mips.h +++ /dev/null @@ -1,160 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#include -#include - -#ifdef mips -# undef mips -#endif - -#define UNW_TARGET mips -#define UNW_TARGET_MIPS 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* This needs to be big enough to accommodate "struct cursor", while - leaving some slack for future expansion. Changing this value will - require recompiling all users of this library. Stack allocation is - relatively cheap and unwind-state copying is relatively rare, so we - want to err on making it rather too big than too small. */ - -/* FIXME for MIPS. Too big? What do other things use for similar tasks? */ -#define UNW_TDEP_CURSOR_LEN 4096 - -/* The size of a "word" varies on MIPS. This type is used for memory - addresses and register values, which are 32-bit wide for O32 and N32 - ABIs, and 64-bit wide for N64 ABI. */ -#if _MIPS_SIM == _ABI64 -typedef uint64_t unw_word_t; -#else -typedef uint32_t unw_word_t; -#endif -typedef int32_t unw_sword_t; - -/* FIXME: MIPS ABIs. */ -typedef long double unw_tdep_fpreg_t; - -typedef enum - { - UNW_MIPS_R0, - UNW_MIPS_R1, - UNW_MIPS_R2, - UNW_MIPS_R3, - UNW_MIPS_R4, - UNW_MIPS_R5, - UNW_MIPS_R6, - UNW_MIPS_R7, - UNW_MIPS_R8, - UNW_MIPS_R9, - UNW_MIPS_R10, - UNW_MIPS_R11, - UNW_MIPS_R12, - UNW_MIPS_R13, - UNW_MIPS_R14, - UNW_MIPS_R15, - UNW_MIPS_R16, - UNW_MIPS_R17, - UNW_MIPS_R18, - UNW_MIPS_R19, - UNW_MIPS_R20, - UNW_MIPS_R21, - UNW_MIPS_R22, - UNW_MIPS_R23, - UNW_MIPS_R24, - UNW_MIPS_R25, - UNW_MIPS_R26, - UNW_MIPS_R27, - UNW_MIPS_R28, - UNW_MIPS_R29, - UNW_MIPS_R30, - UNW_MIPS_R31, - - UNW_MIPS_PC = 34, - - /* FIXME: Other registers! */ - - /* For MIPS, the CFA is the value of SP (r29) at the call site in the - previous frame. */ - UNW_MIPS_CFA, - - UNW_TDEP_LAST_REG = UNW_MIPS_PC, - - UNW_TDEP_IP = UNW_MIPS_R31, - UNW_TDEP_SP = UNW_MIPS_R29, - UNW_TDEP_EH = UNW_MIPS_R0 /* FIXME. */ - } -mips_regnum_t; - -typedef enum - { - UNW_MIPS_ABI_O32, - UNW_MIPS_ABI_N32, - UNW_MIPS_ABI_N64 - } -mips_abi_t; - -#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for MIPS. */ - -typedef struct unw_tdep_save_loc - { - /* Additional target-dependent info on a save location. */ - } -unw_tdep_save_loc_t; - -/* On x86, we can directly use ucontext_t as the unwind context. FIXME for - MIPS. */ -typedef ucontext_t unw_tdep_context_t; - -#include "libunwind-dynamic.h" - -typedef struct - { - /* no mips-specific auxiliary proc-info */ - } -unw_tdep_proc_info_t; - -#include "libunwind-common.h" - -/* There is no getcontext() on MIPS. Use a stub version which only saves GP - registers. FIXME: Not ideal, may not be sufficient for all libunwind - use cases. */ -#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext) -extern int unw_tdep_getcontext (ucontext_t *uc); - -#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) -extern int unw_tdep_is_fpreg (int); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/contrib/libunwind/include/libunwind-ppc32.h b/contrib/libunwind/include/libunwind-ppc32.h deleted file mode 100644 index 47ebfde5a3c..00000000000 --- a/contrib/libunwind/include/libunwind-ppc32.h +++ /dev/null @@ -1,207 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - - Copied from libunwind-x86_64.h, modified slightly for building - frysk successfully on ppc64, by Wu Zhou - Will be replaced when libunwind is ready on ppc64 platform. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#include -#include - -#define UNW_TARGET ppc32 -#define UNW_TARGET_PPC32 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* - * This needs to be big enough to accommodate "struct cursor", while - * leaving some slack for future expansion. Changing this value will - * require recompiling all users of this library. Stack allocation is - * relatively cheap and unwind-state copying is relatively rare, so we want - * to err on making it rather too big than too small. - * - * To simplify this whole process, we are at least initially taking the - * tack that UNW_PPC32_* map straight across to the .eh_frame column register - * numbers. These register numbers come from gcc's source in - * gcc/config/rs6000/rs6000.h - * - * UNW_TDEP_CURSOR_LEN is in terms of unw_word_t size. Since we have 115 - * elements in the loc array, each sized 2 * unw_word_t, plus the rest of - * the cursor struct, this puts us at about 2 * 115 + 40 = 270. Let's - * round that up to 280. - */ - -#define UNW_TDEP_CURSOR_LEN 280 - -#if __WORDSIZE==32 -typedef uint32_t unw_word_t; -typedef int32_t unw_sword_t; -#else -typedef uint64_t unw_word_t; -typedef int64_t unw_sword_t; -#endif - -typedef long double unw_tdep_fpreg_t; - -typedef enum - { - UNW_PPC32_R0, - UNW_PPC32_R1, /* called STACK_POINTER in gcc */ - UNW_PPC32_R2, - UNW_PPC32_R3, - UNW_PPC32_R4, - UNW_PPC32_R5, - UNW_PPC32_R6, - UNW_PPC32_R7, - UNW_PPC32_R8, - UNW_PPC32_R9, - UNW_PPC32_R10, - UNW_PPC32_R11, /* called STATIC_CHAIN in gcc */ - UNW_PPC32_R12, - UNW_PPC32_R13, - UNW_PPC32_R14, - UNW_PPC32_R15, - UNW_PPC32_R16, - UNW_PPC32_R17, - UNW_PPC32_R18, - UNW_PPC32_R19, - UNW_PPC32_R20, - UNW_PPC32_R21, - UNW_PPC32_R22, - UNW_PPC32_R23, - UNW_PPC32_R24, - UNW_PPC32_R25, - UNW_PPC32_R26, - UNW_PPC32_R27, - UNW_PPC32_R28, - UNW_PPC32_R29, - UNW_PPC32_R30, - UNW_PPC32_R31, /* called HARD_FRAME_POINTER in gcc */ - - /* Count Register */ - UNW_PPC32_CTR = 32, - /* Fixed-Point Status and Control Register */ - UNW_PPC32_XER = 33, - /* Condition Register */ - UNW_PPC32_CCR = 34, - /* Machine State Register */ - //UNW_PPC32_MSR = 35, - /* MQ or SPR0, not part of generic Power, part of MPC601 */ - //UNW_PPC32_MQ = 36, - /* Link Register */ - UNW_PPC32_LR = 36, - /* Floating Pointer Status and Control Register */ - UNW_PPC32_FPSCR = 37, - - UNW_PPC32_F0 = 48, - UNW_PPC32_F1, - UNW_PPC32_F2, - UNW_PPC32_F3, - UNW_PPC32_F4, - UNW_PPC32_F5, - UNW_PPC32_F6, - UNW_PPC32_F7, - UNW_PPC32_F8, - UNW_PPC32_F9, - UNW_PPC32_F10, - UNW_PPC32_F11, - UNW_PPC32_F12, - UNW_PPC32_F13, - UNW_PPC32_F14, - UNW_PPC32_F15, - UNW_PPC32_F16, - UNW_PPC32_F17, - UNW_PPC32_F18, - UNW_PPC32_F19, - UNW_PPC32_F20, - UNW_PPC32_F21, - UNW_PPC32_F22, - UNW_PPC32_F23, - UNW_PPC32_F24, - UNW_PPC32_F25, - UNW_PPC32_F26, - UNW_PPC32_F27, - UNW_PPC32_F28, - UNW_PPC32_F29, - UNW_PPC32_F30, - UNW_PPC32_F31, - - UNW_TDEP_LAST_REG = UNW_PPC32_F31, - - UNW_TDEP_IP = UNW_PPC32_LR, - UNW_TDEP_SP = UNW_PPC32_R1, - UNW_TDEP_EH = UNW_PPC32_R12 - } -ppc32_regnum_t; - -/* - * According to David Edelsohn, GNU gcc uses R3, R4, R5, and maybe R6 for - * passing parameters to exception handlers. - */ - -#define UNW_TDEP_NUM_EH_REGS 4 - -typedef struct unw_tdep_save_loc - { - /* Additional target-dependent info on a save location. */ - } -unw_tdep_save_loc_t; - -/* On ppc, we can directly use ucontext_t as the unwind context. */ -typedef ucontext_t unw_tdep_context_t; - -/* XXX this is not ideal: an application should not be prevented from - using the "getcontext" name just because it's using libunwind. We - can't just use __getcontext() either, because that isn't exported - by glibc... */ -#define unw_tdep_getcontext(uc) (getcontext (uc), 0) - -#include "libunwind-dynamic.h" - -typedef struct - { - /* no ppc32-specific auxiliary proc-info */ - } -unw_tdep_proc_info_t; - -#include "libunwind-common.h" - -#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) -extern int unw_tdep_is_fpreg (int); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/contrib/libunwind/include/libunwind-ppc64.h b/contrib/libunwind/include/libunwind-ppc64.h deleted file mode 100644 index 9944628da02..00000000000 --- a/contrib/libunwind/include/libunwind-ppc64.h +++ /dev/null @@ -1,271 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - - Copied from libunwind-x86_64.h, modified slightly for building - frysk successfully on ppc64, by Wu Zhou - Will be replaced when libunwind is ready on ppc64 platform. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#include -#include - -#define UNW_TARGET ppc64 -#define UNW_TARGET_PPC64 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* - * This needs to be big enough to accommodate "struct cursor", while - * leaving some slack for future expansion. Changing this value will - * require recompiling all users of this library. Stack allocation is - * relatively cheap and unwind-state copying is relatively rare, so we want - * to err on making it rather too big than too small. - * - * To simplify this whole process, we are at least initially taking the - * tack that UNW_PPC64_* map straight across to the .eh_frame column register - * numbers. These register numbers come from gcc's source in - * gcc/config/rs6000/rs6000.h - * - * UNW_TDEP_CURSOR_LEN is in terms of unw_word_t size. Since we have 115 - * elements in the loc array, each sized 2 * unw_word_t, plus the rest of - * the cursor struct, this puts us at about 2 * 115 + 40 = 270. Let's - * round that up to 280. - */ - -#define UNW_TDEP_CURSOR_LEN 280 - -#if __WORDSIZE==32 -typedef uint32_t unw_word_t; -typedef int32_t unw_sword_t; -#else -typedef uint64_t unw_word_t; -typedef int64_t unw_sword_t; -#endif - -typedef long double unw_tdep_fpreg_t; - -/* - * Vector register (in PowerPC64 used for AltiVec registers) - */ -typedef struct { - uint64_t halves[2]; -} unw_tdep_vreg_t; - -typedef enum - { - UNW_PPC64_R0, - UNW_PPC64_R1, /* called STACK_POINTER in gcc */ - UNW_PPC64_R2, - UNW_PPC64_R3, - UNW_PPC64_R4, - UNW_PPC64_R5, - UNW_PPC64_R6, - UNW_PPC64_R7, - UNW_PPC64_R8, - UNW_PPC64_R9, - UNW_PPC64_R10, - UNW_PPC64_R11, /* called STATIC_CHAIN in gcc */ - UNW_PPC64_R12, - UNW_PPC64_R13, - UNW_PPC64_R14, - UNW_PPC64_R15, - UNW_PPC64_R16, - UNW_PPC64_R17, - UNW_PPC64_R18, - UNW_PPC64_R19, - UNW_PPC64_R20, - UNW_PPC64_R21, - UNW_PPC64_R22, - UNW_PPC64_R23, - UNW_PPC64_R24, - UNW_PPC64_R25, - UNW_PPC64_R26, - UNW_PPC64_R27, - UNW_PPC64_R28, - UNW_PPC64_R29, - UNW_PPC64_R30, - UNW_PPC64_R31, /* called HARD_FRAME_POINTER in gcc */ - - UNW_PPC64_F0 = 32, - UNW_PPC64_F1, - UNW_PPC64_F2, - UNW_PPC64_F3, - UNW_PPC64_F4, - UNW_PPC64_F5, - UNW_PPC64_F6, - UNW_PPC64_F7, - UNW_PPC64_F8, - UNW_PPC64_F9, - UNW_PPC64_F10, - UNW_PPC64_F11, - UNW_PPC64_F12, - UNW_PPC64_F13, - UNW_PPC64_F14, - UNW_PPC64_F15, - UNW_PPC64_F16, - UNW_PPC64_F17, - UNW_PPC64_F18, - UNW_PPC64_F19, - UNW_PPC64_F20, - UNW_PPC64_F21, - UNW_PPC64_F22, - UNW_PPC64_F23, - UNW_PPC64_F24, - UNW_PPC64_F25, - UNW_PPC64_F26, - UNW_PPC64_F27, - UNW_PPC64_F28, - UNW_PPC64_F29, - UNW_PPC64_F30, - UNW_PPC64_F31, - /* Note that there doesn't appear to be an .eh_frame register column - for the FPSCR register. I don't know why this is. Since .eh_frame - info is what this implementation uses for unwinding, we have no way - to unwind this register, and so we will not expose an FPSCR register - number in the libunwind API. - */ - - UNW_PPC64_LR = 65, - UNW_PPC64_CTR = 66, - UNW_PPC64_ARG_POINTER = 67, - - UNW_PPC64_CR0 = 68, - UNW_PPC64_CR1, - UNW_PPC64_CR2, - UNW_PPC64_CR3, - UNW_PPC64_CR4, - /* CR5 .. CR7 are currently unused */ - UNW_PPC64_CR5, - UNW_PPC64_CR6, - UNW_PPC64_CR7, - - UNW_PPC64_XER = 76, - - UNW_PPC64_V0 = 77, - UNW_PPC64_V1, - UNW_PPC64_V2, - UNW_PPC64_V3, - UNW_PPC64_V4, - UNW_PPC64_V5, - UNW_PPC64_V6, - UNW_PPC64_V7, - UNW_PPC64_V8, - UNW_PPC64_V9, - UNW_PPC64_V10, - UNW_PPC64_V11, - UNW_PPC64_V12, - UNW_PPC64_V13, - UNW_PPC64_V14, - UNW_PPC64_V15, - UNW_PPC64_V16, - UNW_PPC64_V17, - UNW_PPC64_V18, - UNW_PPC64_V19, - UNW_PPC64_V20, - UNW_PPC64_V21, - UNW_PPC64_V22, - UNW_PPC64_V23, - UNW_PPC64_V24, - UNW_PPC64_V25, - UNW_PPC64_V26, - UNW_PPC64_V27, - UNW_PPC64_V28, - UNW_PPC64_V29, - UNW_PPC64_V30, - UNW_PPC64_V31, - - UNW_PPC64_VRSAVE = 109, - UNW_PPC64_VSCR = 110, - UNW_PPC64_SPE_ACC = 111, - UNW_PPC64_SPEFSCR = 112, - - /* frame info (read-only) */ - UNW_PPC64_FRAME_POINTER, - UNW_PPC64_NIP, - - - UNW_TDEP_LAST_REG = UNW_PPC64_NIP, - - UNW_TDEP_IP = UNW_PPC64_NIP, - UNW_TDEP_SP = UNW_PPC64_R1, - UNW_TDEP_EH = UNW_PPC64_R12 - } -ppc64_regnum_t; - -typedef enum - { - UNW_PPC64_ABI_ELFv1, - UNW_PPC64_ABI_ELFv2 - } -ppc64_abi_t; - -/* - * According to David Edelsohn, GNU gcc uses R3, R4, R5, and maybe R6 for - * passing parameters to exception handlers. - */ - -#define UNW_TDEP_NUM_EH_REGS 4 - -typedef struct unw_tdep_save_loc - { - /* Additional target-dependent info on a save location. */ - } -unw_tdep_save_loc_t; - -/* On ppc64, we can directly use ucontext_t as the unwind context. */ -typedef ucontext_t unw_tdep_context_t; - -/* XXX this is not ideal: an application should not be prevented from - using the "getcontext" name just because it's using libunwind. We - can't just use __getcontext() either, because that isn't exported - by glibc... */ -#define unw_tdep_getcontext(uc) (getcontext (uc), 0) - -#include "libunwind-dynamic.h" - -typedef struct - { - /* no ppc64-specific auxiliary proc-info */ - } -unw_tdep_proc_info_t; - -#include "libunwind-common.h" - -#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) -extern int unw_tdep_is_fpreg (int); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/contrib/libunwind/include/libunwind-ptrace.h b/contrib/libunwind/include/libunwind-ptrace.h deleted file mode 100644 index 801325c4d4d..00000000000 --- a/contrib/libunwind/include/libunwind-ptrace.h +++ /dev/null @@ -1,63 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef libunwind_ptrace_h -#define libunwind_ptrace_h - -#include - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -/* Helper routines which make it easy to use libunwind via ptrace(). - They're available only if UNW_REMOTE_ONLY is _not_ defined and they - aren't really part of the libunwind API. They are implemented in a - archive library called libunwind-ptrace.a. */ - -extern void *_UPT_create (pid_t); -extern void _UPT_destroy (void *); -extern int _UPT_find_proc_info (unw_addr_space_t, unw_word_t, - unw_proc_info_t *, int, void *); -extern void _UPT_put_unwind_info (unw_addr_space_t, unw_proc_info_t *, void *); -extern int _UPT_get_dyn_info_list_addr (unw_addr_space_t, unw_word_t *, - void *); -extern int _UPT_access_mem (unw_addr_space_t, unw_word_t, unw_word_t *, int, - void *); -extern int _UPT_access_reg (unw_addr_space_t, unw_regnum_t, unw_word_t *, - int, void *); -extern int _UPT_access_fpreg (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, - int, void *); -extern int _UPT_get_proc_name (unw_addr_space_t, unw_word_t, char *, size_t, - unw_word_t *, void *); -extern int _UPT_resume (unw_addr_space_t, unw_cursor_t *, void *); -extern unw_accessors_t _UPT_accessors; - - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* libunwind_ptrace_h */ diff --git a/contrib/libunwind/include/libunwind-sh.h b/contrib/libunwind/include/libunwind-sh.h deleted file mode 100644 index 927f61ff42b..00000000000 --- a/contrib/libunwind/include/libunwind-sh.h +++ /dev/null @@ -1,114 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#include -#include -#include - -#define UNW_TARGET sh -#define UNW_TARGET_SH 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* This needs to be big enough to accommodate "struct cursor", while - leaving some slack for future expansion. Changing this value will - require recompiling all users of this library. Stack allocation is - relatively cheap and unwind-state copying is relatively rare, so we - want to err on making it rather too big than too small. */ - -#define UNW_TDEP_CURSOR_LEN 4096 - -typedef uint32_t unw_word_t; -typedef int32_t unw_sword_t; - -typedef long double unw_tdep_fpreg_t; - -typedef enum - { - UNW_SH_R0, - UNW_SH_R1, - UNW_SH_R2, - UNW_SH_R3, - UNW_SH_R4, - UNW_SH_R5, - UNW_SH_R6, - UNW_SH_R7, - UNW_SH_R8, - UNW_SH_R9, - UNW_SH_R10, - UNW_SH_R11, - UNW_SH_R12, - UNW_SH_R13, - UNW_SH_R14, - UNW_SH_R15, - - UNW_SH_PC, - UNW_SH_PR, - - UNW_TDEP_LAST_REG = UNW_SH_PR, - - UNW_TDEP_IP = UNW_SH_PR, - UNW_TDEP_SP = UNW_SH_R15, - UNW_TDEP_EH = UNW_SH_R0 - } -sh_regnum_t; - -#define UNW_TDEP_NUM_EH_REGS 2 - -typedef ucontext_t unw_tdep_context_t; - -#define unw_tdep_getcontext(uc) (getcontext (uc), 0) - -typedef struct unw_tdep_save_loc - { - /* Additional target-dependent info on a save location. */ - } -unw_tdep_save_loc_t; - -#include "libunwind-dynamic.h" - -typedef struct - { - /* no sh-specific auxiliary proc-info */ - } -unw_tdep_proc_info_t; - -#include "libunwind-common.h" - -#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) -extern int unw_tdep_is_fpreg (int); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/contrib/libunwind/include/libunwind-tilegx.h b/contrib/libunwind/include/libunwind-tilegx.h deleted file mode 100644 index 0f84ea65ee3..00000000000 --- a/contrib/libunwind/include/libunwind-tilegx.h +++ /dev/null @@ -1,161 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#include -#include - -#define UNW_TARGET tilegx -#define UNW_TARGET_TILEGX 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* This needs to be big enough to accommodate "struct cursor", while - leaving some slack for future expansion. Changing this value will - require recompiling all users of this library. Stack allocation is - relatively cheap and unwind-state copying is relatively rare, so we - want to err on making it rather too big than too small. */ - -#define UNW_TDEP_CURSOR_LEN 4096 - -/* The size of a "word" varies on TILEGX. This type is used for memory - addresses and register values. */ -typedef uint64_t unw_word_t; -typedef int64_t unw_sword_t; - -typedef long double unw_tdep_fpreg_t; - -typedef enum -{ - UNW_TILEGX_R0, - UNW_TILEGX_R1, - UNW_TILEGX_R2, - UNW_TILEGX_R3, - UNW_TILEGX_R4, - UNW_TILEGX_R5, - UNW_TILEGX_R6, - UNW_TILEGX_R7, - UNW_TILEGX_R8, - UNW_TILEGX_R9, - UNW_TILEGX_R10, - UNW_TILEGX_R11, - UNW_TILEGX_R12, - UNW_TILEGX_R13, - UNW_TILEGX_R14, - UNW_TILEGX_R15, - UNW_TILEGX_R16, - UNW_TILEGX_R17, - UNW_TILEGX_R18, - UNW_TILEGX_R19, - UNW_TILEGX_R20, - UNW_TILEGX_R21, - UNW_TILEGX_R22, - UNW_TILEGX_R23, - UNW_TILEGX_R24, - UNW_TILEGX_R25, - UNW_TILEGX_R26, - UNW_TILEGX_R27, - UNW_TILEGX_R28, - UNW_TILEGX_R29, - UNW_TILEGX_R30, - UNW_TILEGX_R31, - UNW_TILEGX_R32, - UNW_TILEGX_R33, - UNW_TILEGX_R34, - UNW_TILEGX_R35, - UNW_TILEGX_R36, - UNW_TILEGX_R37, - UNW_TILEGX_R38, - UNW_TILEGX_R39, - UNW_TILEGX_R40, - UNW_TILEGX_R41, - UNW_TILEGX_R42, - UNW_TILEGX_R43, - UNW_TILEGX_R44, - UNW_TILEGX_R45, - UNW_TILEGX_R46, - UNW_TILEGX_R47, - UNW_TILEGX_R48, - UNW_TILEGX_R49, - UNW_TILEGX_R50, - UNW_TILEGX_R51, - UNW_TILEGX_R52, - UNW_TILEGX_R53, - UNW_TILEGX_R54, - UNW_TILEGX_R55, - - /* FIXME: Other registers! */ - - UNW_TILEGX_PC, - /* For TILEGX, the CFA is the value of SP (r54) at the call site in the - previous frame. */ - UNW_TILEGX_CFA, - - UNW_TDEP_LAST_REG = UNW_TILEGX_PC, - - UNW_TDEP_IP = UNW_TILEGX_R55, /* R55 is link register for Tilegx */ - UNW_TDEP_SP = UNW_TILEGX_R54, - UNW_TDEP_EH = UNW_TILEGX_R0 /* FIXME. */ -} tilegx_regnum_t; - -typedef enum -{ - UNW_TILEGX_ABI_N64 = 2 -} tilegx_abi_t; - -#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for TILEGX. */ - -typedef struct unw_tdep_save_loc -{ - /* Additional target-dependent info on a save location. */ -} unw_tdep_save_loc_t; - -typedef ucontext_t unw_tdep_context_t; - -#include "libunwind-dynamic.h" - -typedef struct -{ - /* no tilegx-specific auxiliary proc-info */ -} unw_tdep_proc_info_t; - -#include "libunwind-common.h" - -#define unw_tdep_getcontext getcontext - -#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) -extern int unw_tdep_is_fpreg (int); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/contrib/libunwind/include/libunwind-x86.h b/contrib/libunwind/include/libunwind-x86.h deleted file mode 100644 index 40fe0464f2f..00000000000 --- a/contrib/libunwind/include/libunwind-x86.h +++ /dev/null @@ -1,187 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#include -#include -#include - -#define UNW_TARGET x86 -#define UNW_TARGET_X86 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* This needs to be big enough to accommodate "struct cursor", while - leaving some slack for future expansion. Changing this value will - require recompiling all users of this library. Stack allocation is - relatively cheap and unwind-state copying is relatively rare, so we - want to err on making it rather too big than too small. */ -#define UNW_TDEP_CURSOR_LEN 127 - -typedef uint32_t unw_word_t; -typedef int32_t unw_sword_t; - -typedef union { - struct { uint8_t b[4]; } val32; - struct { uint8_t b[10]; } val80; - struct { uint8_t b[16]; } val128; -} unw_tdep_fpreg_t; - -typedef enum - { - /* Note: general registers are expected to start with index 0. - This convention facilitates architecture-independent - implementation of the C++ exception handling ABI. See - _Unwind_SetGR() and _Unwind_GetGR() for details. - - The described register usage convention is based on "System V - Application Binary Interface, Intel386 Architecture Processor - Supplement, Fourth Edition" at - - http://www.linuxbase.org/spec/refspecs/elf/abi386-4.pdf - - It would have been nice to use the same register numbering as - DWARF, but that doesn't work because the libunwind requires - that the exception argument registers be consecutive, which the - wouldn't be with the DWARF numbering. */ - UNW_X86_EAX, /* scratch (exception argument 1) */ - UNW_X86_EDX, /* scratch (exception argument 2) */ - UNW_X86_ECX, /* scratch */ - UNW_X86_EBX, /* preserved */ - UNW_X86_ESI, /* preserved */ - UNW_X86_EDI, /* preserved */ - UNW_X86_EBP, /* (optional) frame-register */ - UNW_X86_ESP, /* (optional) frame-register */ - UNW_X86_EIP, /* frame-register */ - UNW_X86_EFLAGS, /* scratch (except for "direction", which is fixed */ - UNW_X86_TRAPNO, /* scratch */ - - /* MMX/stacked-fp registers */ - UNW_X86_ST0, /* fp return value */ - UNW_X86_ST1, /* scratch */ - UNW_X86_ST2, /* scratch */ - UNW_X86_ST3, /* scratch */ - UNW_X86_ST4, /* scratch */ - UNW_X86_ST5, /* scratch */ - UNW_X86_ST6, /* scratch */ - UNW_X86_ST7, /* scratch */ - - UNW_X86_FCW, /* scratch */ - UNW_X86_FSW, /* scratch */ - UNW_X86_FTW, /* scratch */ - UNW_X86_FOP, /* scratch */ - UNW_X86_FCS, /* scratch */ - UNW_X86_FIP, /* scratch */ - UNW_X86_FEA, /* scratch */ - UNW_X86_FDS, /* scratch */ - - /* SSE registers */ - UNW_X86_XMM0_lo, /* scratch */ - UNW_X86_XMM0_hi, /* scratch */ - UNW_X86_XMM1_lo, /* scratch */ - UNW_X86_XMM1_hi, /* scratch */ - UNW_X86_XMM2_lo, /* scratch */ - UNW_X86_XMM2_hi, /* scratch */ - UNW_X86_XMM3_lo, /* scratch */ - UNW_X86_XMM3_hi, /* scratch */ - UNW_X86_XMM4_lo, /* scratch */ - UNW_X86_XMM4_hi, /* scratch */ - UNW_X86_XMM5_lo, /* scratch */ - UNW_X86_XMM5_hi, /* scratch */ - UNW_X86_XMM6_lo, /* scratch */ - UNW_X86_XMM6_hi, /* scratch */ - UNW_X86_XMM7_lo, /* scratch */ - UNW_X86_XMM7_hi, /* scratch */ - - UNW_X86_MXCSR, /* scratch */ - - /* segment registers */ - UNW_X86_GS, /* special */ - UNW_X86_FS, /* special */ - UNW_X86_ES, /* special */ - UNW_X86_DS, /* special */ - UNW_X86_SS, /* special */ - UNW_X86_CS, /* special */ - UNW_X86_TSS, /* special */ - UNW_X86_LDT, /* special */ - - /* frame info (read-only) */ - UNW_X86_CFA, - - UNW_X86_XMM0, /* scratch */ - UNW_X86_XMM1, /* scratch */ - UNW_X86_XMM2, /* scratch */ - UNW_X86_XMM3, /* scratch */ - UNW_X86_XMM4, /* scratch */ - UNW_X86_XMM5, /* scratch */ - UNW_X86_XMM6, /* scratch */ - UNW_X86_XMM7, /* scratch */ - - UNW_TDEP_LAST_REG = UNW_X86_XMM7, - - UNW_TDEP_IP = UNW_X86_EIP, - UNW_TDEP_SP = UNW_X86_ESP, - UNW_TDEP_EH = UNW_X86_EAX - } -x86_regnum_t; - -#define UNW_TDEP_NUM_EH_REGS 2 /* eax and edx are exception args */ - -typedef struct unw_tdep_save_loc - { - /* Additional target-dependent info on a save location. */ - } -unw_tdep_save_loc_t; - -/* On x86, we can directly use ucontext_t as the unwind context. */ -typedef ucontext_t unw_tdep_context_t; - -#include "libunwind-dynamic.h" - -typedef struct - { - /* no x86-specific auxiliary proc-info */ - } -unw_tdep_proc_info_t; - -#include "libunwind-common.h" - -#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext) -extern int unw_tdep_getcontext (unw_tdep_context_t *); - -#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) -extern int unw_tdep_is_fpreg (int); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/contrib/libunwind/include/libunwind-x86_64.h b/contrib/libunwind/include/libunwind-x86_64.h deleted file mode 100644 index 78eb541afb3..00000000000 --- a/contrib/libunwind/include/libunwind-x86_64.h +++ /dev/null @@ -1,141 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#include -#include -#include - -#define UNW_TARGET x86_64 -#define UNW_TARGET_X86_64 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* This needs to be big enough to accommodate "struct cursor", while - leaving some slack for future expansion. Changing this value will - require recompiling all users of this library. Stack allocation is - relatively cheap and unwind-state copying is relatively rare, so we - want to err on making it rather too big than too small. */ -#define UNW_TDEP_CURSOR_LEN 127 - -typedef uint64_t unw_word_t; -typedef int64_t unw_sword_t; - -typedef long double unw_tdep_fpreg_t; - -typedef enum - { - UNW_X86_64_RAX, - UNW_X86_64_RDX, - UNW_X86_64_RCX, - UNW_X86_64_RBX, - UNW_X86_64_RSI, - UNW_X86_64_RDI, - UNW_X86_64_RBP, - UNW_X86_64_RSP, - UNW_X86_64_R8, - UNW_X86_64_R9, - UNW_X86_64_R10, - UNW_X86_64_R11, - UNW_X86_64_R12, - UNW_X86_64_R13, - UNW_X86_64_R14, - UNW_X86_64_R15, - UNW_X86_64_RIP, -#ifdef CONFIG_MSABI_SUPPORT - UNW_X86_64_XMM0, - UNW_X86_64_XMM1, - UNW_X86_64_XMM2, - UNW_X86_64_XMM3, - UNW_X86_64_XMM4, - UNW_X86_64_XMM5, - UNW_X86_64_XMM6, - UNW_X86_64_XMM7, - UNW_X86_64_XMM8, - UNW_X86_64_XMM9, - UNW_X86_64_XMM10, - UNW_X86_64_XMM11, - UNW_X86_64_XMM12, - UNW_X86_64_XMM13, - UNW_X86_64_XMM14, - UNW_X86_64_XMM15, - UNW_TDEP_LAST_REG = UNW_X86_64_XMM15, -#else - UNW_TDEP_LAST_REG = UNW_X86_64_RIP, -#endif - - /* XXX Add other regs here */ - - /* frame info (read-only) */ - UNW_X86_64_CFA, - - UNW_TDEP_IP = UNW_X86_64_RIP, - UNW_TDEP_SP = UNW_X86_64_RSP, - UNW_TDEP_BP = UNW_X86_64_RBP, - UNW_TDEP_EH = UNW_X86_64_RAX - } -x86_64_regnum_t; - -#define UNW_TDEP_NUM_EH_REGS 2 /* XXX Not sure what this means */ - -typedef struct unw_tdep_save_loc - { - /* Additional target-dependent info on a save location. */ - char unused; - } -unw_tdep_save_loc_t; - -/* On x86_64, we can directly use ucontext_t as the unwind context. */ -typedef ucontext_t unw_tdep_context_t; - -typedef struct - { - /* no x86-64-specific auxiliary proc-info */ - char unused; - } -unw_tdep_proc_info_t; - -#include "libunwind-dynamic.h" -#include "libunwind-common.h" - -#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext) -#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) - -extern int unw_tdep_getcontext (unw_tdep_context_t *); -extern int unw_tdep_is_fpreg (int); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/contrib/libunwind/include/libunwind.h.in b/contrib/libunwind/include/libunwind.h.in deleted file mode 100644 index 7a56168c8b2..00000000000 --- a/contrib/libunwind/include/libunwind.h.in +++ /dev/null @@ -1,36 +0,0 @@ -/* Provide a real file - not a symlink - as it would cause multiarch conflicts - when multiple different arch releases are installed simultaneously. */ - -#ifndef UNW_REMOTE_ONLY - -#if defined __aarch64__ -#include "libunwind-aarch64.h" -#elif defined __arm__ -# include "libunwind-arm.h" -#elif defined __hppa__ -# include "libunwind-hppa.h" -#elif defined __ia64__ -# include "libunwind-ia64.h" -#elif defined __mips__ -# include "libunwind-mips.h" -#elif defined __powerpc__ && !defined __powerpc64__ -# include "libunwind-ppc32.h" -#elif defined __powerpc64__ -# include "libunwind-ppc64.h" -#elif defined __sh__ -# include "libunwind-sh.h" -#elif defined __i386__ -# include "libunwind-x86.h" -#elif defined __x86_64__ -# include "libunwind-x86_64.h" -#elif defined __tilegx__ -# include "libunwind-tilegx.h" -#else -# error "Unsupported arch" -#endif - -#else /* UNW_REMOTE_ONLY */ - -# include "libunwind-@arch@.h" - -#endif /* UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/include/libunwind_i.h b/contrib/libunwind/include/libunwind_i.h deleted file mode 100644 index 36cf7a14de7..00000000000 --- a/contrib/libunwind/include/libunwind_i.h +++ /dev/null @@ -1,365 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2005 Hewlett-Packard Co - Copyright (C) 2007 David Mosberger-Tang - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* This files contains libunwind-internal definitions which are - subject to frequent change and are not to be exposed to - libunwind-users. */ - -#ifndef libunwind_i_h -#define libunwind_i_h - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "compiler.h" - -#if defined(HAVE___THREAD) && HAVE___THREAD -#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_PER_THREAD -#else -#define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_GLOBAL -#endif - -/* Platform-independent libunwind-internal declarations. */ - -#include /* HP-UX needs this before include of pthread.h */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(HAVE_ELF_H) -# include -#elif defined(HAVE_SYS_ELF_H) -# include -#else -# error Could not locate -#endif - -#if defined(HAVE_ENDIAN_H) -# include -#elif defined(HAVE_SYS_ENDIAN_H) -# include -# if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN) -# define __LITTLE_ENDIAN _LITTLE_ENDIAN -# endif -# if defined(_BIG_ENDIAN) && !defined(__BIG_ENDIAN) -# define __BIG_ENDIAN _BIG_ENDIAN -# endif -# if defined(_BYTE_ORDER) && !defined(__BYTE_ORDER) -# define __BYTE_ORDER _BYTE_ORDER -# endif -#else -# define __LITTLE_ENDIAN 1234 -# define __BIG_ENDIAN 4321 -# if defined(__hpux) -# define __BYTE_ORDER __BIG_ENDIAN -# elif defined(__QNX__) -# if defined(__BIGENDIAN__) -# define __BYTE_ORDER __BIG_ENDIAN -# elif defined(__LITTLEENDIAN__) -# define __BYTE_ORDER __LITTLE_ENDIAN -# else -# error Host has unknown byte-order. -# endif -# else -# error Host has unknown byte-order. -# endif -#endif - -#if defined(HAVE__BUILTIN_UNREACHABLE) -# define unreachable() __builtin_unreachable() -#else -# define unreachable() do { } while (1) -#endif - -#ifdef DEBUG -# define UNW_DEBUG 1 -#else -# define UNW_DEBUG 0 -#endif - -/* Make it easy to write thread-safe code which may or may not be - linked against libpthread. The macros below can be used - unconditionally and if -lpthread is around, they'll call the - corresponding routines otherwise, they do nothing. */ - -#pragma weak pthread_mutex_init -#pragma weak pthread_mutex_lock -#pragma weak pthread_mutex_unlock - -#define mutex_init(l) \ - (pthread_mutex_init != NULL ? pthread_mutex_init ((l), NULL) : 0) -#define mutex_lock(l) \ - (pthread_mutex_lock != NULL ? pthread_mutex_lock (l) : 0) -#define mutex_unlock(l) \ - (pthread_mutex_unlock != NULL ? pthread_mutex_unlock (l) : 0) - -#ifdef HAVE_ATOMIC_OPS_H -# include -static inline int -cmpxchg_ptr (void *addr, void *old, void *new) -{ - union - { - void *vp; - AO_t *aop; - } - u; - - u.vp = addr; - return AO_compare_and_swap(u.aop, (AO_t) old, (AO_t) new); -} -# define fetch_and_add1(_ptr) AO_fetch_and_add1(_ptr) -# define fetch_and_add(_ptr, value) AO_fetch_and_add(_ptr, value) - /* GCC 3.2.0 on HP-UX crashes on cmpxchg_ptr() */ -# if !(defined(__hpux) && __GNUC__ == 3 && __GNUC_MINOR__ == 2) -# define HAVE_CMPXCHG -# endif -# define HAVE_FETCH_AND_ADD -#elif defined(HAVE_SYNC_ATOMICS) || defined(HAVE_IA64INTRIN_H) -# ifdef HAVE_IA64INTRIN_H -# include -# endif -static inline int -cmpxchg_ptr (void *addr, void *old, void *new) -{ - union - { - void *vp; - long *vlp; - } - u; - - u.vp = addr; - return __sync_bool_compare_and_swap(u.vlp, (long) old, (long) new); -} -# define fetch_and_add1(_ptr) __sync_fetch_and_add(_ptr, 1) -# define fetch_and_add(_ptr, value) __sync_fetch_and_add(_ptr, value) -# define HAVE_CMPXCHG -# define HAVE_FETCH_AND_ADD -#endif -#define atomic_read(ptr) (*(ptr)) - -#define UNWI_OBJ(fn) UNW_PASTE(UNW_PREFIX,UNW_PASTE(I,fn)) -#define UNWI_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_UI,UNW_TARGET),_), fn) - -#define unwi_full_mask UNWI_ARCH_OBJ(full_mask) - -/* Type of a mask that can be used to inhibit preemption. At the - userlevel, preemption is caused by signals and hence sigset_t is - appropriate. In constrast, the Linux kernel uses "unsigned long" - to hold the processor "flags" instead. */ -typedef sigset_t intrmask_t; - -extern intrmask_t unwi_full_mask; - -/* Silence compiler warnings about variables which are used only if libunwind - is configured in a certain way */ -static inline void mark_as_used(void *v UNUSED) { -} - -#if defined(CONFIG_BLOCK_SIGNALS) -# define SIGPROCMASK(how, new_mask, old_mask) \ - sigprocmask((how), (new_mask), (old_mask)) -#else -# define SIGPROCMASK(how, new_mask, old_mask) mark_as_used(old_mask) -#endif - -/* Prefer adaptive mutexes if available */ -#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP -#define UNW_PTHREAD_MUTEX_INITIALIZER PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP -#else -#define UNW_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER -#endif - -#define define_lock(name) \ - pthread_mutex_t name = UNW_PTHREAD_MUTEX_INITIALIZER -#define lock_init(l) mutex_init (l) -#define lock_acquire(l,m) \ -do { \ - SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &(m)); \ - mutex_lock (l); \ -} while (0) -#define lock_release(l,m) \ -do { \ - mutex_unlock (l); \ - SIGPROCMASK (SIG_SETMASK, &(m), NULL); \ -} while (0) - -#define SOS_MEMORY_SIZE 16384 /* see src/mi/mempool.c */ - -#ifndef MAP_ANONYMOUS -# define MAP_ANONYMOUS MAP_ANON -#endif -#define GET_MEMORY(mem, size) \ -do { \ - /* Hopefully, mmap() goes straight through to a system call stub... */ \ - mem = mmap (NULL, size, PROT_READ | PROT_WRITE, \ - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \ - if (mem == MAP_FAILED) \ - mem = NULL; \ -} while (0) - -#define unwi_find_dynamic_proc_info UNWI_OBJ(find_dynamic_proc_info) -#define unwi_extract_dynamic_proc_info UNWI_OBJ(extract_dynamic_proc_info) -#define unwi_put_dynamic_unwind_info UNWI_OBJ(put_dynamic_unwind_info) -#define unwi_dyn_remote_find_proc_info UNWI_OBJ(dyn_remote_find_proc_info) -#define unwi_dyn_remote_put_unwind_info UNWI_OBJ(dyn_remote_put_unwind_info) -#define unwi_dyn_validate_cache UNWI_OBJ(dyn_validate_cache) - -extern int unwi_find_dynamic_proc_info (unw_addr_space_t as, - unw_word_t ip, - unw_proc_info_t *pi, - int need_unwind_info, void *arg); -extern int unwi_extract_dynamic_proc_info (unw_addr_space_t as, - unw_word_t ip, - unw_proc_info_t *pi, - unw_dyn_info_t *di, - int need_unwind_info, - void *arg); -extern void unwi_put_dynamic_unwind_info (unw_addr_space_t as, - unw_proc_info_t *pi, void *arg); - -/* These handle the remote (cross-address-space) case of accessing - dynamic unwind info. */ - -extern int unwi_dyn_remote_find_proc_info (unw_addr_space_t as, - unw_word_t ip, - unw_proc_info_t *pi, - int need_unwind_info, - void *arg); -extern void unwi_dyn_remote_put_unwind_info (unw_addr_space_t as, - unw_proc_info_t *pi, - void *arg); -extern int unwi_dyn_validate_cache (unw_addr_space_t as, void *arg); - -extern unw_dyn_info_list_t _U_dyn_info_list; -extern pthread_mutex_t _U_dyn_info_list_lock; - -#if UNW_DEBUG -#define unwi_debug_level UNWI_ARCH_OBJ(debug_level) -extern long unwi_debug_level; - -# include -# define Debug(level,format...) \ -do { \ - if (unwi_debug_level >= level) \ - { \ - int _n = level; \ - if (_n > 16) \ - _n = 16; \ - fprintf (stderr, "%*c>%s: ", _n, ' ', __FUNCTION__); \ - fprintf (stderr, format); \ - } \ -} while (0) -# define Dprintf(format...) fprintf (stderr, format) -#else -# define Debug(level,format...) -# define Dprintf(format...) -#endif - -static ALWAYS_INLINE int -print_error (const char *string) -{ - return write (2, string, strlen (string)); -} - -#define mi_init UNWI_ARCH_OBJ(mi_init) - -extern void mi_init (void); /* machine-independent initializations */ -extern unw_word_t _U_dyn_info_list_addr (void); - -/* This is needed/used by ELF targets only. */ - -struct elf_image - { - void *image; /* pointer to mmap'd image */ - size_t size; /* (file-) size of the image */ - }; - -struct elf_dyn_info - { - struct elf_image ei; - unw_dyn_info_t di_cache; - unw_dyn_info_t di_debug; /* additional table info for .debug_frame */ -#if UNW_TARGET_IA64 - unw_dyn_info_t ktab; -#endif -#if UNW_TARGET_ARM - unw_dyn_info_t di_arm; /* additional table info for .ARM.exidx */ -#endif - }; - -static inline void invalidate_edi (struct elf_dyn_info *edi) -{ - if (edi->ei.image) - munmap (edi->ei.image, edi->ei.size); - memset (edi, 0, sizeof (*edi)); - edi->di_cache.format = -1; - edi->di_debug.format = -1; -#if UNW_TARGET_ARM - edi->di_arm.format = -1; -#endif -} - - -/* Provide a place holder for architecture to override for fast access - to memory when known not to need to validate and know the access - will be local to the process. A suitable override will improve - unw_tdep_trace() performance in particular. */ -#define ACCESS_MEM_FAST(ret,validate,cur,addr,to) \ - do { (ret) = dwarf_get ((cur), DWARF_MEM_LOC ((cur), (addr)), &(to)); } \ - while (0) - -/* Define GNU and processor specific values for the Phdr p_type field in case - they aren't defined by . */ -#ifndef PT_GNU_EH_FRAME -# define PT_GNU_EH_FRAME 0x6474e550 -#endif /* !PT_GNU_EH_FRAME */ -#ifndef PT_ARM_EXIDX -# define PT_ARM_EXIDX 0x70000001 /* ARM unwind segment */ -#endif /* !PT_ARM_EXIDX */ - -#include "tdep/libunwind_i.h" - -#ifndef tdep_get_func_addr -# define tdep_get_func_addr(as,addr,v) (*(v) = addr, 0) -#endif - -#ifndef DWARF_VAL_LOC -# define DWARF_IS_VAL_LOC(l) 0 -# define DWARF_VAL_LOC(c,v) DWARF_NULL_LOC -#endif - -#define UNW_ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL)) - -#endif /* libunwind_i_h */ diff --git a/contrib/libunwind/include/mempool.h b/contrib/libunwind/include/mempool.h deleted file mode 100644 index 1f1c7700993..00000000000 --- a/contrib/libunwind/include/mempool.h +++ /dev/null @@ -1,89 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef mempool_h -#define mempool_h - -/* Memory pools provide simple memory management of fixed-size - objects. Memory pools are used for two purposes: - - o To ensure a stack can be unwound even when a process - is out of memory. - - o To ensure a stack can be unwound at any time in a - multi-threaded process (e.g., even at a time when the normal - malloc-lock is taken, possibly by the very thread that is - being unwind). - - - To achieve the second objective, memory pools allocate memory - directly via mmap() system call (or an equivalent facility). - - The first objective is accomplished by reserving memory ahead of - time. Since the memory requirements of stack unwinding generally - depends on the complexity of the procedures being unwind, there is - no absolute guarantee that unwinding will always work, but in - practice, this should not be a serious problem. */ - -#include - -#include "libunwind_i.h" - -#define sos_alloc(s) UNWI_ARCH_OBJ(_sos_alloc)(s) -#define mempool_init(p,s,r) UNWI_ARCH_OBJ(_mempool_init)(p,s,r) -#define mempool_alloc(p) UNWI_ARCH_OBJ(_mempool_alloc)(p) -#define mempool_free(p,o) UNWI_ARCH_OBJ(_mempool_free)(p,o) - -/* The mempool structure should be treated as an opaque object. It's - declared here only to enable static allocation of mempools. */ -struct mempool - { - pthread_mutex_t lock; - size_t obj_size; /* object size (rounded up for alignment) */ - size_t chunk_size; /* allocation granularity */ - unsigned int reserve; /* minimum (desired) size of the free-list */ - unsigned int num_free; /* number of objects on the free-list */ - struct object - { - struct object *next; - } - *free_list; - }; - -/* Emergency allocation for one-time stuff that doesn't fit the memory - pool model. A limited amount of memory is available in this - fashion and once allocated, there is no way to free it. */ -extern void *sos_alloc (size_t size); - -/* Initialize POOL for an object size of OBJECT_SIZE bytes. RESERVE - is the number of objects that should be reserved for use under - tight memory situations. If it is zero, mempool attempts to pick a - reasonable default value. */ -extern void mempool_init (struct mempool *pool, - size_t obj_size, size_t reserve); -extern void *mempool_alloc (struct mempool *pool); -extern void mempool_free (struct mempool *pool, void *object); - -#endif /* mempool_h */ diff --git a/contrib/libunwind/include/remote.h b/contrib/libunwind/include/remote.h deleted file mode 100644 index 064d6309adb..00000000000 --- a/contrib/libunwind/include/remote.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef REMOTE_H -#define REMOTE_H - -/* Helper functions for accessing (remote) memory. These functions - assume that all addresses are naturally aligned (e.g., 32-bit - quantity is stored at a 32-bit-aligned address. */ - -#ifdef UNW_LOCAL_ONLY - -static inline int -fetch8 (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, int8_t *valp, void *arg) -{ - *valp = *(int8_t *) (uintptr_t) *addr; - *addr += 1; - return 0; -} - -static inline int -fetch16 (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, int16_t *valp, void *arg) -{ - *valp = *(int16_t *) (uintptr_t) *addr; - *addr += 2; - return 0; -} - -static inline int -fetch32 (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, int32_t *valp, void *arg) -{ - *valp = *(int32_t *) (uintptr_t) *addr; - *addr += 4; - return 0; -} - -static inline int -fetchw (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, unw_word_t *valp, void *arg) -{ - *valp = *(unw_word_t *) (uintptr_t) *addr; - *addr += sizeof (unw_word_t); - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ - -#define WSIZE (sizeof (unw_word_t)) - -static inline int -fetch8 (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, int8_t *valp, void *arg) -{ - unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr; - int ret; - - *addr += 1; - - ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); - -#if __BYTE_ORDER == __LITTLE_ENDIAN - val >>= 8*off; -#else - val >>= 8*(WSIZE - 1 - off); -#endif - *valp = val & 0xff; - return ret; -} - -static inline int -fetch16 (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, int16_t *valp, void *arg) -{ - unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr; - int ret; - - if ((off & 0x1) != 0) - return -UNW_EINVAL; - - *addr += 2; - - ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); - -#if __BYTE_ORDER == __LITTLE_ENDIAN - val >>= 8*off; -#else - val >>= 8*(WSIZE - 2 - off); -#endif - *valp = val & 0xffff; - return ret; -} - -static inline int -fetch32 (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, int32_t *valp, void *arg) -{ - unw_word_t val, aligned_addr = *addr & -WSIZE, off = *addr - aligned_addr; - int ret; - - if ((off & 0x3) != 0) - return -UNW_EINVAL; - - *addr += 4; - - ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); - -#if __BYTE_ORDER == __LITTLE_ENDIAN - val >>= 8*off; -#else - val >>= 8*(WSIZE - 4 - off); -#endif - *valp = val & 0xffffffff; - return ret; -} - -static inline int -fetchw (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, unw_word_t *valp, void *arg) -{ - int ret; - - ret = (*a->access_mem) (as, *addr, valp, 0, arg); - *addr += WSIZE; - return ret; -} - -#endif /* !UNW_LOCAL_ONLY */ - -#endif /* REMOTE_H */ diff --git a/contrib/libunwind/include/tdep-aarch64/dwarf-config.h b/contrib/libunwind/include/tdep-aarch64/dwarf-config.h deleted file mode 100644 index f65db17ee65..00000000000 --- a/contrib/libunwind/include/tdep-aarch64/dwarf-config.h +++ /dev/null @@ -1,52 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_config_h -#define dwarf_config_h - -/* This matches the value udes by GCC (see - gcc/config/aarch64/aarch64.h:DWARF_FRAME_REGISTERS. */ -#define DWARF_NUM_PRESERVED_REGS 97 - -/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) 0 - -#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_AARCH64_V31) ? (reg) : 0) - -/* Convert a pointer to a dwarf_cursor structure to a pointer to - unw_cursor_t. */ -#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) - -typedef struct dwarf_loc - { - unw_word_t val; -#ifndef UNW_LOCAL_ONLY - unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ -#endif - } -dwarf_loc_t; - -#endif /* dwarf_config_h */ diff --git a/contrib/libunwind/include/tdep-aarch64/jmpbuf.h b/contrib/libunwind/include/tdep-aarch64/jmpbuf.h deleted file mode 100644 index 3f01a442baf..00000000000 --- a/contrib/libunwind/include/tdep-aarch64/jmpbuf.h +++ /dev/null @@ -1,33 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -/* FIXME for AArch64 */ - -#define JB_SP 13 -#define JB_RP 14 -#define JB_MASK_SAVED 15 -#define JB_MASK 16 diff --git a/contrib/libunwind/include/tdep-aarch64/libunwind_i.h b/contrib/libunwind/include/tdep-aarch64/libunwind_i.h deleted file mode 100644 index b91273fa1c5..00000000000 --- a/contrib/libunwind/include/tdep-aarch64/libunwind_i.h +++ /dev/null @@ -1,320 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef AARCH64_LIBUNWIND_I_H -#define AARCH64_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include -#include - -#include "elf64.h" -#include "mempool.h" -#include "dwarf.h" - -typedef enum - { - UNW_AARCH64_FRAME_STANDARD = -2, /* regular fp, sp +/- offset */ - UNW_AARCH64_FRAME_SIGRETURN = -1, /* special sigreturn frame */ - UNW_AARCH64_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */ - UNW_AARCH64_FRAME_GUESSED = 1 /* guessed it was regular, but not known */ - } -unw_tdep_frame_type_t; - -typedef struct - { - uint64_t virtual_address; - int64_t frame_type : 2; /* unw_tdep_frame_type_t classification */ - int64_t last_frame : 1; /* non-zero if last frame in chain */ - int64_t cfa_reg_sp : 1; /* cfa dwarf base register is sp vs. fp */ - int64_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */ - int64_t fp_cfa_offset : 30; /* fp saved at this offset from cfa (-1 = not saved) */ - int64_t lr_cfa_offset : 30; /* lr saved at this offset from cfa (-1 = not saved) */ - int64_t sp_cfa_offset : 30; /* sp saved at this offset from cfa (-1 = not saved) */ - } -unw_tdep_frame_t; - -#ifdef UNW_LOCAL_ONLY - -typedef unw_word_t aarch64_loc_t; - -#else /* !UNW_LOCAL_ONLY */ - -typedef struct aarch64_loc - { - unw_word_t w0, w1; - } -aarch64_loc_t; - -#endif /* !UNW_LOCAL_ONLY */ - -struct unw_addr_space - { - struct unw_accessors acc; - int big_endian; - unw_caching_policy_t caching_policy; -#ifdef HAVE_ATOMIC_OPS_H - AO_t cache_generation; -#else - uint32_t cache_generation; -#endif - unw_word_t dyn_generation; /* see dyn-common.h */ - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ - struct dwarf_rs_cache global_cache; - struct unw_debug_frame_list *debug_frames; - }; - -struct cursor - { - struct dwarf_cursor dwarf; /* must be first */ - - unw_tdep_frame_t frame_info; /* quick tracing assist info */ - - enum - { - AARCH64_SCF_NONE, - AARCH64_SCF_LINUX_RT_SIGFRAME, - } - sigcontext_format; - unw_word_t sigcontext_addr; - unw_word_t sigcontext_sp; - unw_word_t sigcontext_pc; - int validate; - }; - -#define DWARF_GET_LOC(l) ((l).val) - -#ifdef UNW_LOCAL_ONLY -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) -# define DWARF_IS_REG_LOC(l) 0 -# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_word_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_word_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ -# define DWARF_LOC_TYPE_FP (1 << 0) -# define DWARF_LOC_TYPE_REG (1 << 1) -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) \ - ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) -# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_FP)) - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - val, 0, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 0, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0, - c->as_arg); -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - &val, 1, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 1, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, - 1, c->as_arg); -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - - - -#define tdep_getcontext_trace UNW_ARCH_OBJ(getcontext_trace) -#define tdep_init_done UNW_OBJ(init_done) -#define tdep_init UNW_OBJ(init) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table dwarf_search_unwind_table -#define tdep_find_unwind_table dwarf_find_unwind_table -#define tdep_uc_addr UNW_OBJ(uc_addr) -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#define tdep_fetch_frame(c,ip,n) do {} while(0) -#define tdep_cache_frame(c) 0 -#define tdep_reuse_frame(c,frame) do {} while(0) -#define tdep_stash_frame UNW_OBJ(tdep_stash_frame) -#define tdep_trace UNW_OBJ(tdep_trace) - -#ifdef UNW_LOCAL_ONLY -# define tdep_find_proc_info(c,ip,n) \ - dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - dwarf_put_unwind_info((as), (pi), (arg)) -#else -# define tdep_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - (*(as)->acc.put_unwind_info)((as), (pi), (arg)) -#endif - -#define tdep_get_as(c) ((c)->dwarf.as) -#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) -#define tdep_get_ip(c) ((c)->dwarf.ip) -#define tdep_big_endian(as) ((as)->big_endian) - -extern int tdep_init_done; - -extern void tdep_init (void); -extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg); -extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg); -extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, - unw_word_t *valp, int write); -extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, - unw_fpreg_t *valp, int write); -extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n); -extern void tdep_stash_frame (struct dwarf_cursor *c, - struct dwarf_reg_state *rs); -extern int tdep_getcontext_trace (unw_tdep_context_t *); - -#endif /* AARCH64_LIBUNWIND_I_H */ diff --git a/contrib/libunwind/include/tdep-arm/dwarf-config.h b/contrib/libunwind/include/tdep-arm/dwarf-config.h deleted file mode 100644 index f50228975ec..00000000000 --- a/contrib/libunwind/include/tdep-arm/dwarf-config.h +++ /dev/null @@ -1,51 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_config_h -#define dwarf_config_h - -/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not - explicitly defined. */ -#define DWARF_NUM_PRESERVED_REGS 128 - -#define dwarf_to_unw_regnum(reg) (((reg) < 16) ? (reg) : 0) - -/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) 0 - -/* Convert a pointer to a dwarf_cursor structure to a pointer to - unw_cursor_t. */ -#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) - -typedef struct dwarf_loc - { - unw_word_t val; -#ifndef UNW_LOCAL_ONLY - unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ -#endif - } -dwarf_loc_t; - -#endif /* dwarf_config_h */ diff --git a/contrib/libunwind/include/tdep-arm/ex_tables.h b/contrib/libunwind/include/tdep-arm/ex_tables.h deleted file mode 100644 index 9df5e0a9fa4..00000000000 --- a/contrib/libunwind/include/tdep-arm/ex_tables.h +++ /dev/null @@ -1,55 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright 2011 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef ARM_EX_TABLES_H -#define ARM_EX_TABLES_H - -typedef enum arm_exbuf_cmd { - ARM_EXIDX_CMD_FINISH, - ARM_EXIDX_CMD_DATA_PUSH, - ARM_EXIDX_CMD_DATA_POP, - ARM_EXIDX_CMD_REG_POP, - ARM_EXIDX_CMD_REG_TO_SP, - ARM_EXIDX_CMD_VFP_POP, - ARM_EXIDX_CMD_WREG_POP, - ARM_EXIDX_CMD_WCGR_POP, - ARM_EXIDX_CMD_RESERVED, - ARM_EXIDX_CMD_REFUSED, -} arm_exbuf_cmd_t; - -struct arm_exbuf_data -{ - arm_exbuf_cmd_t cmd; - uint32_t data; -}; - -#define arm_exidx_extract UNW_OBJ(arm_exidx_extract) -#define arm_exidx_decode UNW_OBJ(arm_exidx_decode) -#define arm_exidx_apply_cmd UNW_OBJ(arm_exidx_apply_cmd) - -int arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf); -int arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c); -int arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c); - -#endif // ARM_EX_TABLES_H diff --git a/contrib/libunwind/include/tdep-arm/jmpbuf.h b/contrib/libunwind/include/tdep-arm/jmpbuf.h deleted file mode 100644 index 008e77f7960..00000000000 --- a/contrib/libunwind/include/tdep-arm/jmpbuf.h +++ /dev/null @@ -1,32 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -/* FIXME for ARM! */ - -#define JB_SP 4 -#define JB_RP 5 -#define JB_MASK_SAVED 6 -#define JB_MASK 7 diff --git a/contrib/libunwind/include/tdep-arm/libunwind_i.h b/contrib/libunwind/include/tdep-arm/libunwind_i.h deleted file mode 100644 index 2602f41c4f7..00000000000 --- a/contrib/libunwind/include/tdep-arm/libunwind_i.h +++ /dev/null @@ -1,326 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef ARM_LIBUNWIND_I_H -#define ARM_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include -#include - -#include "elf32.h" -#include "mempool.h" -#include "dwarf.h" -#include "ex_tables.h" - -typedef enum - { - UNW_ARM_FRAME_SYSCALL = -3, /* r7 saved in r12, sp offset zero */ - UNW_ARM_FRAME_STANDARD = -2, /* regular r7, sp +/- offset */ - UNW_ARM_FRAME_SIGRETURN = -1, /* special sigreturn frame */ - UNW_ARM_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */ - UNW_ARM_FRAME_GUESSED = 1 /* guessed it was regular, but not known */ - } -unw_tdep_frame_type_t; - -typedef struct - { - uint32_t virtual_address; - int32_t frame_type : 3; /* unw_tdep_frame_type_t classification */ - int32_t last_frame : 1; /* non-zero if last frame in chain */ - int32_t cfa_reg_sp : 1; /* cfa dwarf base register is sp vs. r7 */ - int32_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */ - int32_t r7_cfa_offset : 30; /* r7 saved at this offset from cfa (-1 = not saved) */ - int32_t lr_cfa_offset : 30; /* lr saved at this offset from cfa (-1 = not saved) */ - int32_t sp_cfa_offset : 30; /* sp saved at this offset from cfa (-1 = not saved) */ - } -unw_tdep_frame_t; - -struct unw_addr_space - { - struct unw_accessors acc; - int big_endian; - unw_caching_policy_t caching_policy; -#ifdef HAVE_ATOMIC_OPS_H - AO_t cache_generation; -#else - uint32_t cache_generation; -#endif - unw_word_t dyn_generation; /* see dyn-common.h */ - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ - struct dwarf_rs_cache global_cache; - struct unw_debug_frame_list *debug_frames; - }; - -struct cursor - { - struct dwarf_cursor dwarf; /* must be first */ - - unw_tdep_frame_t frame_info; /* quick tracing assist info */ - - enum - { - ARM_SCF_NONE, /* no signal frame */ - ARM_SCF_LINUX_SIGFRAME, /* non-RT signal frame, kernel >=2.6.18 */ - ARM_SCF_LINUX_RT_SIGFRAME, /* RT signal frame, kernel >=2.6.18 */ - ARM_SCF_LINUX_OLD_SIGFRAME, /* non-RT signal frame, kernel < 2.6.18 */ - ARM_SCF_LINUX_OLD_RT_SIGFRAME, /* RT signal frame, kernel < 2.6.18 */ - ARM_SCF_FREEBSD_SIGFRAME, /* FreeBSD sigframe */ - ARM_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall stub */ - } - sigcontext_format; - unw_word_t sigcontext_addr; - unw_word_t sigcontext_sp; - unw_word_t sigcontext_pc; - int validate; - }; - -#define DWARF_GET_LOC(l) ((l).val) - -#ifdef UNW_LOCAL_ONLY -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) -# define DWARF_IS_REG_LOC(l) 0 -# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_word_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_word_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ -# define DWARF_LOC_TYPE_FP (1 << 0) -# define DWARF_LOC_TYPE_REG (1 << 1) -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) \ - ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) -# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_FP)) - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - val, 0, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 0, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0, - c->as_arg); -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - &val, 1, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 1, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, - 1, c->as_arg); -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - -#define tdep_getcontext_trace unw_getcontext -#define tdep_init_done UNW_OBJ(init_done) -#define tdep_init UNW_OBJ(init) -#define arm_find_proc_info UNW_OBJ(find_proc_info) -#define arm_put_unwind_info UNW_OBJ(put_unwind_info) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table UNW_OBJ(search_unwind_table) -#define tdep_find_unwind_table dwarf_find_unwind_table -#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#define tdep_fetch_frame(c,ip,n) do {} while(0) -#define tdep_cache_frame(c) 0 -#define tdep_reuse_frame(c,frame) do {} while(0) -#define tdep_stash_frame UNW_OBJ(tdep_stash_frame) -#define tdep_trace UNW_OBJ(tdep_trace) - -#ifdef UNW_LOCAL_ONLY -# define tdep_find_proc_info(c,ip,n) \ - arm_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - arm_put_unwind_info((as), (pi), (arg)) -#else -# define tdep_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - (*(as)->acc.put_unwind_info)((as), (pi), (arg)) -#endif - -#define tdep_get_as(c) ((c)->dwarf.as) -#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) -#define tdep_get_ip(c) ((c)->dwarf.ip) -#define tdep_big_endian(as) ((as)->big_endian) - -extern int tdep_init_done; - -extern void tdep_init (void); -extern int arm_find_proc_info (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, int need_unwind_info, - void *arg); -extern void arm_put_unwind_info (unw_addr_space_t as, - unw_proc_info_t *pi, void *arg); -extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg); -extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg); -extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, - unw_word_t *valp, int write); -extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, - unw_fpreg_t *valp, int write); -extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n); -extern void tdep_stash_frame (struct dwarf_cursor *c, - struct dwarf_reg_state *rs); - -/* unwinding method selection support */ -#define UNW_ARM_METHOD_ALL 0xFF -#define UNW_ARM_METHOD_DWARF 0x01 -#define UNW_ARM_METHOD_FRAME 0x02 -#define UNW_ARM_METHOD_EXIDX 0x04 - -#define unwi_unwind_method UNW_OBJ(unwind_method) -extern int unwi_unwind_method; - -#define UNW_TRY_METHOD(x) (unwi_unwind_method & x) - -#endif /* ARM_LIBUNWIND_I_H */ diff --git a/contrib/libunwind/include/tdep-hppa/dwarf-config.h b/contrib/libunwind/include/tdep-hppa/dwarf-config.h deleted file mode 100644 index fb963c7d307..00000000000 --- a/contrib/libunwind/include/tdep-hppa/dwarf-config.h +++ /dev/null @@ -1,54 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2004 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_config_h -#define dwarf_config_h - -/* See DWARF_FRAME_REGNUM() macro in gcc/config/pa/pa32-regs.h: */ -#define dwarf_to_unw_regnum(reg) \ - (((reg) < DWARF_NUM_PRESERVED_REGS) ? (reg) : 0) - -/* This matches the value used by GCC (see - gcc/config/pa/pa32-regs.h:FIRST_PSEUDO_REGISTER), which leaves - plenty of room for expansion. */ -#define DWARF_NUM_PRESERVED_REGS 89 - -/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) 1 - -/* Convert a pointer to a dwarf_cursor structure to a pointer to - unw_cursor_t. */ -#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) - -typedef struct dwarf_loc - { - unw_word_t val; -#ifndef UNW_LOCAL_ONLY - unw_word_t type; /* see X86_LOC_TYPE_* macros. */ -#endif - } -dwarf_loc_t; - -#endif /* dwarf_config_h */ diff --git a/contrib/libunwind/include/tdep-hppa/jmpbuf.h b/contrib/libunwind/include/tdep-hppa/jmpbuf.h deleted file mode 100644 index 91f062ff7df..00000000000 --- a/contrib/libunwind/include/tdep-hppa/jmpbuf.h +++ /dev/null @@ -1,33 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -#ifndef JB_SP -# define JB_SP 19 -#endif -#define JB_RP 20 -#define JB_MASK_SAVED 21 -#define JB_MASK 22 diff --git a/contrib/libunwind/include/tdep-hppa/libunwind_i.h b/contrib/libunwind/include/tdep-hppa/libunwind_i.h deleted file mode 100644 index 72649aa3ecc..00000000000 --- a/contrib/libunwind/include/tdep-hppa/libunwind_i.h +++ /dev/null @@ -1,279 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef HPPA_LIBUNWIND_I_H -#define HPPA_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include -#include - -#include "elf32.h" -#include "mempool.h" -#include "dwarf.h" - -typedef struct - { - /* no hppa-specific fast trace */ - } -unw_tdep_frame_t; - -struct unw_addr_space - { - struct unw_accessors acc; - unw_caching_policy_t caching_policy; -#ifdef HAVE_ATOMIC_OPS_H - AO_t cache_generation; -#else - uint32_t cache_generation; -#endif - unw_word_t dyn_generation; /* see dyn-common.h */ - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ - struct dwarf_rs_cache global_cache; - struct unw_debug_frame_list *debug_frames; - }; - -struct cursor - { - struct dwarf_cursor dwarf; /* must be first */ - - /* Format of sigcontext structure and address at which it is - stored: */ - enum - { - HPPA_SCF_NONE, /* no signal frame encountered */ - HPPA_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */ - } - sigcontext_format; - unw_word_t sigcontext_addr; - }; - -#define DWARF_GET_LOC(l) ((l).val) - -#ifdef UNW_LOCAL_ONLY -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) -# define DWARF_IS_REG_LOC(l) 0 -# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_word_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_word_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ -# define DWARF_LOC_TYPE_FP (1 << 0) -# define DWARF_LOC_TYPE_REG (1 << 1) -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) \ - ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) -# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_FP)) - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - val, 0, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 0, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0, - c->as_arg); -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - &val, 1, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 1, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, - 1, c->as_arg); -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - -#define tdep_getcontext_trace unw_getcontext -#define tdep_init_done UNW_OBJ(init_done) -#define tdep_init UNW_OBJ(init) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table dwarf_search_unwind_table -#define tdep_find_unwind_table dwarf_find_unwind_table -#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#define tdep_fetch_frame(c,ip,n) do {} while(0) -#define tdep_cache_frame(c) 0 -#define tdep_reuse_frame(c,frame) do {} while(0) -#define tdep_stash_frame(c,rs) do {} while(0) -#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) - -#ifdef UNW_LOCAL_ONLY -# define tdep_find_proc_info(c,ip,n) \ - dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - dwarf_put_unwind_info((as), (pi), (arg)) -#else -# define tdep_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - (*(as)->acc.put_unwind_info)((as), (pi), (arg)) -#endif - -#define tdep_get_as(c) ((c)->dwarf.as) -#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) -#define tdep_get_ip(c) ((c)->dwarf.ip) -#define tdep_big_endian(as) 1 - -extern int tdep_init_done; - -extern void tdep_init (void); -extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg); -extern void *tdep_uc_addr (ucontext_t *uc, int reg); -extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, - unw_word_t *valp, int write); -extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, - unw_fpreg_t *valp, int write); - -#endif /* HPPA_LIBUNWIND_I_H */ diff --git a/contrib/libunwind/include/tdep-ia64/jmpbuf.h b/contrib/libunwind/include/tdep-ia64/jmpbuf.h deleted file mode 100644 index d642af2075a..00000000000 --- a/contrib/libunwind/include/tdep-ia64/jmpbuf.h +++ /dev/null @@ -1,32 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP and BSP: */ - -#define JB_SP 0 -#define JB_RP 8 -#define JB_BSP 17 -#define JB_MASK_SAVED 70 -#define JB_MASK 71 diff --git a/contrib/libunwind/include/tdep-ia64/libunwind_i.h b/contrib/libunwind/include/tdep-ia64/libunwind_i.h deleted file mode 100644 index f2cf258efaf..00000000000 --- a/contrib/libunwind/include/tdep-ia64/libunwind_i.h +++ /dev/null @@ -1,281 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef IA64_LIBUNWIND_I_H -#define IA64_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include "elf64.h" -#include "mempool.h" - -typedef struct - { - /* no ia64-specific fast trace */ - } -unw_tdep_frame_t; - -enum ia64_pregnum - { - /* primary unat: */ - IA64_REG_PRI_UNAT_GR, - IA64_REG_PRI_UNAT_MEM, - - /* memory stack (order matters: see build_script() */ - IA64_REG_PSP, /* previous memory stack pointer */ - /* register stack */ - IA64_REG_BSP, /* register stack pointer */ - IA64_REG_BSPSTORE, - IA64_REG_PFS, /* previous function state */ - IA64_REG_RNAT, - /* instruction pointer: */ - IA64_REG_IP, - - /* preserved registers: */ - IA64_REG_R4, IA64_REG_R5, IA64_REG_R6, IA64_REG_R7, - IA64_REG_NAT4, IA64_REG_NAT5, IA64_REG_NAT6, IA64_REG_NAT7, - IA64_REG_UNAT, IA64_REG_PR, IA64_REG_LC, IA64_REG_FPSR, - IA64_REG_B1, IA64_REG_B2, IA64_REG_B3, IA64_REG_B4, IA64_REG_B5, - IA64_REG_F2, IA64_REG_F3, IA64_REG_F4, IA64_REG_F5, - IA64_REG_F16, IA64_REG_F17, IA64_REG_F18, IA64_REG_F19, - IA64_REG_F20, IA64_REG_F21, IA64_REG_F22, IA64_REG_F23, - IA64_REG_F24, IA64_REG_F25, IA64_REG_F26, IA64_REG_F27, - IA64_REG_F28, IA64_REG_F29, IA64_REG_F30, IA64_REG_F31, - IA64_NUM_PREGS - }; - -#ifdef UNW_LOCAL_ONLY - -typedef unw_word_t ia64_loc_t; - -#else /* !UNW_LOCAL_ONLY */ - -typedef struct ia64_loc - { - unw_word_t w0, w1; - } -ia64_loc_t; - -#endif /* !UNW_LOCAL_ONLY */ - -#include "script.h" - -#define ABI_UNKNOWN 0 -#define ABI_LINUX 1 -#define ABI_HPUX 2 -#define ABI_FREEBSD 3 -#define ABI_OPENVMS 4 -#define ABI_NSK 5 /* Tandem/HP Non-Stop Kernel */ -#define ABI_WINDOWS 6 - -struct unw_addr_space - { - struct unw_accessors acc; - int big_endian; - int abi; /* abi < 0 => unknown, 0 => SysV, 1 => HP-UX, 2 => Windows */ - unw_caching_policy_t caching_policy; -#ifdef HAVE_ATOMIC_OPS_H - AO_t cache_generation; -#else - uint32_t cache_generation; -#endif - unw_word_t dyn_generation; - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ -#ifndef UNW_REMOTE_ONLY - unsigned long long shared_object_removals; -#endif - - struct ia64_script_cache global_cache; - }; - -/* Note: The ABI numbers in the ABI-markers (.unwabi directive) are - not the same as the above ABI numbers. */ -#define ABI_MARKER_OLD_LINUX_SIGTRAMP ((0 << 8) | 's') -#define ABI_MARKER_OLD_LINUX_INTERRUPT ((0 << 8) | 'i') -#define ABI_MARKER_HP_UX_SIGTRAMP ((1 << 8) | 1) -#define ABI_MARKER_LINUX_SIGTRAMP ((3 << 8) | 's') -#define ABI_MARKER_LINUX_INTERRUPT ((3 << 8) | 'i') - -struct cursor - { - void *as_arg; /* argument to address-space callbacks */ - unw_addr_space_t as; /* reference to per-address-space info */ - - /* IP, CFM, and predicate cache (these are always equal to the - values stored in ip_loc, cfm_loc, and pr_loc, - respectively). */ - unw_word_t ip; /* instruction pointer value */ - unw_word_t cfm; /* current frame mask */ - unw_word_t pr; /* current predicate values */ - - /* current frame info: */ - unw_word_t bsp; /* backing store pointer value */ - unw_word_t sp; /* stack pointer value */ - unw_word_t psp; /* previous sp value */ - ia64_loc_t cfm_loc; /* cfm save location (or NULL) */ - ia64_loc_t ec_loc; /* ar.ec save location (usually cfm_loc) */ - ia64_loc_t loc[IA64_NUM_PREGS]; - - unw_word_t eh_args[4]; /* exception handler arguments */ - unw_word_t sigcontext_addr; /* address of sigcontext or 0 */ - unw_word_t sigcontext_off; /* sigcontext-offset relative to signal sp */ - - short hint; - short prev_script; - - uint8_t nat_bitnr[4]; /* NaT bit numbers for r4-r7 */ - uint16_t abi_marker; /* abi_marker for current frame (if any) */ - uint16_t last_abi_marker; /* last abi_marker encountered so far */ - uint8_t eh_valid_mask; - - unsigned int pi_valid :1; /* is proc_info valid? */ - unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */ - unw_proc_info_t pi; /* info about current procedure */ - - /* In case of stack-discontiguities, such as those introduced by - signal-delivery on an alternate signal-stack (see - sigaltstack(2)), we use the following data-structure to keep - track of the register-backing-store areas across on which the - current frame may be backed up. Since there are at most 96 - stacked registers and since we only have to track the current - frame and only areas that are not empty, this puts an upper - limit on the # of backing-store areas we have to track. - - Note that the rbs-area indexed by rbs_curr identifies the - rbs-area that was in effect at the time AR.BSP had the value - c->bsp. However, this rbs area may not actually contain the - value in the register that c->bsp corresponds to because that - register may not have gotten spilled until much later, when a - possibly different rbs-area might have been in effect - already. */ - uint8_t rbs_curr; /* index of curr. rbs-area (contains c->bsp) */ - uint8_t rbs_left_edge; /* index of inner-most valid rbs-area */ - struct rbs_area - { - unw_word_t end; - unw_word_t size; - ia64_loc_t rnat_loc; - } - rbs_area[96 + 2]; /* 96 stacked regs + 1 extra stack on each side... */ -}; - -struct ia64_global_unwind_state - { - pthread_mutex_t lock; /* global data lock */ - - volatile char init_done; - - /* Table of registers that prologues can save (and order in which - they're saved). */ - const unsigned char save_order[8]; - - /* - * uc_addr() may return pointers to these variables. We need to - * make sure they don't get written via ia64_put() or - * ia64_putfp(). To make it possible to test for these variables - * quickly, we collect them in a single sub-structure. - */ - struct - { - unw_word_t r0; /* r0 is byte-order neutral */ - unw_fpreg_t f0; /* f0 is byte-order neutral */ - unw_fpreg_t f1_le, f1_be; /* f1 is byte-order dependent */ - } - read_only; - unw_fpreg_t nat_val_le, nat_val_be; - unw_fpreg_t int_val_le, int_val_be; - - struct mempool reg_state_pool; - struct mempool labeled_state_pool; - -# if UNW_DEBUG - const char *preg_name[IA64_NUM_PREGS]; -# endif - }; - -#define tdep_getcontext_trace unw_getcontext -#define tdep_init_done unw.init_done -#define tdep_init UNW_OBJ(init) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table unw_search_ia64_unwind_table -#define tdep_find_unwind_table ia64_find_unwind_table -#define tdep_find_proc_info UNW_OBJ(find_proc_info) -#define tdep_uc_addr UNW_OBJ(uc_addr) -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#define tdep_fetch_frame(c,ip,n) do {} while(0) -#define tdep_cache_frame(c) 0 -#define tdep_reuse_frame(c,frame) do {} while(0) -#define tdep_stash_frame(c,rs) do {} while(0) -#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) -#define tdep_get_as(c) ((c)->as) -#define tdep_get_as_arg(c) ((c)->as_arg) -#define tdep_get_ip(c) ((c)->ip) -#define tdep_big_endian(as) ((c)->as->big_endian != 0) - -#ifndef UNW_LOCAL_ONLY -# define tdep_put_unwind_info UNW_OBJ(put_unwind_info) -#endif - -/* This can't be an UNW_ARCH_OBJ() because we need separate - unw.initialized flags for the local-only and generic versions of - the library. Also, if we wanted to have a single, shared global - data structure, we couldn't declare "unw" as HIDDEN/PROTECTED. */ -#define unw UNW_OBJ(data) - -extern void tdep_init (void); -extern int tdep_find_unwind_table (struct elf_dyn_info *edi, - unw_addr_space_t as, char *path, - unw_word_t segbase, unw_word_t mapoff, - unw_word_t ip); -extern int tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, int need_unwind_info, - void *arg); -extern void tdep_put_unwind_info (unw_addr_space_t as, - unw_proc_info_t *pi, void *arg); -extern void *tdep_uc_addr (ucontext_t *uc, unw_regnum_t regnum, - uint8_t *nat_bitnr); -extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, - unw_word_t *valp, int write); -extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, - unw_fpreg_t *valp, int write); - -extern struct ia64_global_unwind_state unw; - -/* In user-level, we have no reasonable way of determining the base of - an arbitrary backing-store. We default to half the - address-space. */ -#define rbs_get_base(c,bspstore,rbs_basep) \ - (*(rbs_basep) = (bspstore) - (((unw_word_t) 1) << 63), 0) - -#endif /* IA64_LIBUNWIND_I_H */ diff --git a/contrib/libunwind/include/tdep-ia64/rse.h b/contrib/libunwind/include/tdep-ia64/rse.h deleted file mode 100644 index ee521a5917a..00000000000 --- a/contrib/libunwind/include/tdep-ia64/rse.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 1998, 1999, 2002, 2003, 2005 Hewlett-Packard Co - * David Mosberger-Tang - * - * Register stack engine related helper functions. This file may be - * used in applications, so be careful about the name-space and give - * some consideration to non-GNU C compilers (though __inline__ is - * fine). - */ -#ifndef RSE_H -#define RSE_H - -#include - -static inline uint64_t -rse_slot_num (uint64_t addr) -{ - return (addr >> 3) & 0x3f; -} - -/* - * Return TRUE if ADDR is the address of an RNAT slot. - */ -static inline uint64_t -rse_is_rnat_slot (uint64_t addr) -{ - return rse_slot_num (addr) == 0x3f; -} - -/* - * Returns the address of the RNAT slot that covers the slot at - * address SLOT_ADDR. - */ -static inline uint64_t -rse_rnat_addr (uint64_t slot_addr) -{ - return slot_addr | (0x3f << 3); -} - -/* - * Calculate the number of registers in the dirty partition starting at - * BSPSTORE and ending at BSP. This isn't simply (BSP-BSPSTORE)/8 - * because every 64th slot stores ar.rnat. - */ -static inline uint64_t -rse_num_regs (uint64_t bspstore, uint64_t bsp) -{ - uint64_t slots = (bsp - bspstore) >> 3; - - return slots - (rse_slot_num(bspstore) + slots)/0x40; -} - -/* - * The inverse of the above: given bspstore and the number of - * registers, calculate ar.bsp. - */ -static inline uint64_t -rse_skip_regs (uint64_t addr, long num_regs) -{ - long delta = rse_slot_num(addr) + num_regs; - - if (num_regs < 0) - delta -= 0x3e; - return addr + ((num_regs + delta/0x3f) << 3); -} - -#endif /* RSE_H */ diff --git a/contrib/libunwind/include/tdep-ia64/script.h b/contrib/libunwind/include/tdep-ia64/script.h deleted file mode 100644 index fe3360bf582..00000000000 --- a/contrib/libunwind/include/tdep-ia64/script.h +++ /dev/null @@ -1,85 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#define IA64_LOG_UNW_CACHE_SIZE 7 -#define IA64_UNW_CACHE_SIZE (1 << IA64_LOG_UNW_CACHE_SIZE) - -#define IA64_LOG_UNW_HASH_SIZE (IA64_LOG_UNW_CACHE_SIZE + 1) -#define IA64_UNW_HASH_SIZE (1 << IA64_LOG_UNW_HASH_SIZE) - -typedef unsigned char unw_hash_index_t; - -struct ia64_script_insn - { - unsigned int opc; /* see enum ia64_script_insn_opcode */ - unsigned int dst; - unw_word_t val; - }; - -/* Updating each preserved register may result in one script - instruction each. At the end of the script, psp gets popped, - accounting for one more instruction. */ -#define IA64_MAX_SCRIPT_LEN (IA64_NUM_PREGS + 1) - -struct ia64_script - { - unw_word_t ip; /* ip this script is for */ - unw_word_t pr_mask; /* mask of predicates script depends on */ - unw_word_t pr_val; /* predicate values this script is for */ - unw_proc_info_t pi; /* info about underlying procedure */ - unsigned short lru_chain; /* used for least-recently-used chain */ - unsigned short coll_chain; /* used for hash collisions */ - unsigned short hint; /* hint for next script to try (or -1) */ - unsigned short count; /* number of instructions in script */ - unsigned short abi_marker; - struct ia64_script_insn insn[IA64_MAX_SCRIPT_LEN]; - }; - -struct ia64_script_cache - { -#ifdef HAVE_ATOMIC_OPS_H - AO_TS_t busy; /* is the script-cache busy? */ -#else - pthread_mutex_t lock; -#endif - unsigned short lru_head; /* index of lead-recently used script */ - unsigned short lru_tail; /* index of most-recently used script */ - - /* hash table that maps instruction pointer to script index: */ - unsigned short hash[IA64_UNW_HASH_SIZE]; - - uint32_t generation; /* generation number */ - - /* script cache: */ - struct ia64_script buckets[IA64_UNW_CACHE_SIZE]; - }; - -#define ia64_cache_proc_info UNW_OBJ(cache_proc_info) -#define ia64_get_cached_proc_info UNW_OBJ(get_cached_proc_info) - -struct cursor; /* forward declaration */ - -extern int ia64_cache_proc_info (struct cursor *c); -extern int ia64_get_cached_proc_info (struct cursor *c); diff --git a/contrib/libunwind/include/tdep-mips/dwarf-config.h b/contrib/libunwind/include/tdep-mips/dwarf-config.h deleted file mode 100644 index 8006d0b8dd4..00000000000 --- a/contrib/libunwind/include/tdep-mips/dwarf-config.h +++ /dev/null @@ -1,54 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_config_h -#define dwarf_config_h - -/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not - explicitly defined. */ -#define DWARF_NUM_PRESERVED_REGS 188 - -#define dwarf_to_unw_regnum(reg) (((reg) < 32) ? (reg) : 0) - -/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) - -/* Return the size of an address, for DWARF purposes. */ -#define dwarf_addr_size(addr_space) ((addr_space)->addr_size) - -/* Convert a pointer to a dwarf_cursor structure to a pointer to - unw_cursor_t. */ -#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) - -typedef struct dwarf_loc - { - unw_word_t val; -#ifndef UNW_LOCAL_ONLY - unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ -#endif - } -dwarf_loc_t; - -#endif /* dwarf_config_h */ diff --git a/contrib/libunwind/include/tdep-mips/jmpbuf.h b/contrib/libunwind/include/tdep-mips/jmpbuf.h deleted file mode 100644 index c099f9267e2..00000000000 --- a/contrib/libunwind/include/tdep-mips/jmpbuf.h +++ /dev/null @@ -1,32 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -/* FIXME for MIPS! */ - -#define JB_SP 4 -#define JB_RP 5 -#define JB_MASK_SAVED 6 -#define JB_MASK 7 diff --git a/contrib/libunwind/include/tdep-mips/libunwind_i.h b/contrib/libunwind/include/tdep-mips/libunwind_i.h deleted file mode 100644 index 3fe40c0c053..00000000000 --- a/contrib/libunwind/include/tdep-mips/libunwind_i.h +++ /dev/null @@ -1,331 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef MIPS_LIBUNWIND_I_H -#define MIPS_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include -#include - -#if !defined(UNW_REMOTE_ONLY) && _MIPS_SIM == _ABI64 -# include "elf64.h" -#else -# include "elf32.h" -#endif -#include "mempool.h" -#include "dwarf.h" - -typedef struct - { - /* no mips-specific fast trace */ - } -unw_tdep_frame_t; - -struct unw_addr_space - { - struct unw_accessors acc; - - int big_endian; - mips_abi_t abi; - unsigned int addr_size; - - unw_caching_policy_t caching_policy; -#ifdef HAVE_ATOMIC_OPS_H - AO_t cache_generation; -#else - uint32_t cache_generation; -#endif - unw_word_t dyn_generation; /* see dyn-common.h */ - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ - struct dwarf_rs_cache global_cache; - struct unw_debug_frame_list *debug_frames; -}; - -#define tdep_big_endian(as) ((as)->big_endian) - -struct cursor - { - struct dwarf_cursor dwarf; /* must be first */ - unw_word_t sigcontext_addr; - }; - -#define DWARF_GET_LOC(l) ((l).val) - -#ifndef UNW_REMOTE_ONLY -# if _MIPS_SIM == _ABIN32 -typedef long long mips_reg_t; -# else -typedef long mips_reg_t; -# endif -#endif - -#ifdef UNW_LOCAL_ONLY -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) -# define DWARF_IS_REG_LOC(l) 0 -# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) - -/* FIXME: Implement these for the MIPS FPU. */ -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc) = val; - return 0; -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(mips_reg_t *) (intptr_t) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(mips_reg_t *) (intptr_t) DWARF_GET_LOC (loc) = val; - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ -# define DWARF_LOC_TYPE_FP (1 << 0) -# define DWARF_LOC_TYPE_REG (1 << 1) -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) \ - ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) -# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_FP)) - -static inline int -read_s32 (struct dwarf_cursor *c, unw_word_t addr, unw_word_t *val) -{ - int offset = addr & 4; - int ret; - unw_word_t memval; - - ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg); - if (ret < 0) - return ret; - - if ((offset != 0) == tdep_big_endian (c->as)) - *val = (int32_t) memval; - else - *val = (int32_t) (memval >> 32); - - return 0; -} - -static inline int -write_s32 (struct dwarf_cursor *c, unw_word_t addr, const unw_word_t *val) -{ - int offset = addr & 4; - int ret; - unw_word_t memval; - - ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg); - if (ret < 0) - return ret; - - if ((offset != 0) == tdep_big_endian (c->as)) - memval = (memval & ~0xffffffffLL) | (uint32_t) *val; - else - memval = (memval & 0xffffffffLL) | (uint32_t) (*val << 32); - - return (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 1, c->as_arg); -} - -/* FIXME: Implement these for the MIPS FPU. */ -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - val, 0, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 0, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0, - c->as_arg); -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - &val, 1, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 1, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, - 1, c->as_arg); -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - else if (c->as->abi == UNW_MIPS_ABI_O32) - return read_s32 (c, DWARF_GET_LOC (loc), val); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); - else if (c->as->abi == UNW_MIPS_ABI_O32) - return write_s32 (c, DWARF_GET_LOC (loc), &val); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - -#define tdep_getcontext_trace unw_getcontext -#define tdep_init_done UNW_OBJ(init_done) -#define tdep_init UNW_OBJ(init) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table dwarf_search_unwind_table -#define tdep_find_unwind_table dwarf_find_unwind_table -#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#define tdep_fetch_frame(c,ip,n) do {} while(0) -#define tdep_cache_frame(c) 0 -#define tdep_reuse_frame(c,frame) do {} while(0) -#define tdep_stash_frame(c,rs) do {} while(0) -#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) - -#ifdef UNW_LOCAL_ONLY -# define tdep_find_proc_info(c,ip,n) \ - dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - dwarf_put_unwind_info((as), (pi), (arg)) -#else -# define tdep_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - (*(as)->acc.put_unwind_info)((as), (pi), (arg)) -#endif - -#define tdep_get_as(c) ((c)->dwarf.as) -#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) -#define tdep_get_ip(c) ((c)->dwarf.ip) - -extern int tdep_init_done; - -extern void tdep_init (void); -extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg); -extern void *tdep_uc_addr (ucontext_t *uc, int reg); -extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, - unw_word_t *valp, int write); -extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, - unw_fpreg_t *valp, int write); - -#endif /* MIPS_LIBUNWIND_I_H */ diff --git a/contrib/libunwind/include/tdep-ppc32/dwarf-config.h b/contrib/libunwind/include/tdep-ppc32/dwarf-config.h deleted file mode 100644 index bf6886b066b..00000000000 --- a/contrib/libunwind/include/tdep-ppc32/dwarf-config.h +++ /dev/null @@ -1,56 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - - Copied from libunwind-x86_64.h, modified slightly for building - frysk successfully on ppc64, by Wu Zhou - Will be replaced when libunwind is ready on ppc64 platform. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_config_h -#define dwarf_config_h - -/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */ -#define DWARF_NUM_PRESERVED_REGS 115 - -#define DWARF_REGNUM_MAP_LENGTH 115 - -/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) 1 - -/* Convert a pointer to a dwarf_cursor structure to a pointer to - unw_cursor_t. */ -#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) - -typedef struct dwarf_loc - { - unw_word_t val; -#ifndef UNW_LOCAL_ONLY - unw_word_t type; /* see X86_LOC_TYPE_* macros. */ -#endif - } -dwarf_loc_t; - -#endif /* dwarf_config_h */ diff --git a/contrib/libunwind/include/tdep-ppc32/jmpbuf.h b/contrib/libunwind/include/tdep-ppc32/jmpbuf.h deleted file mode 100644 index 861e94d9712..00000000000 --- a/contrib/libunwind/include/tdep-ppc32/jmpbuf.h +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - - Copied from libunwind-x86_64.h, modified slightly for building - frysk successfully on ppc64, by Wu Zhou - Will be replaced when libunwind is ready on ppc64 platform. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -#define JB_SP 6 -#define JB_RP 7 -#define JB_MASK_SAVED 8 -#define JB_MASK 9 diff --git a/contrib/libunwind/include/tdep-ppc32/libunwind_i.h b/contrib/libunwind/include/tdep-ppc32/libunwind_i.h deleted file mode 100644 index 4cf6d135f63..00000000000 --- a/contrib/libunwind/include/tdep-ppc32/libunwind_i.h +++ /dev/null @@ -1,314 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - - Copied from libunwind-x86_64.h, modified slightly for building - frysk successfully on ppc64, by Wu Zhou - Will be replaced when libunwind is ready on ppc64 platform. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef PPC32_LIBUNWIND_I_H -#define PPC32_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include -#include - -#include "elf32.h" -#include "mempool.h" -#include "dwarf.h" - -typedef struct - { - /* no ppc32-specific fast trace */ - } -unw_tdep_frame_t; - -struct unw_addr_space -{ - struct unw_accessors acc; - unw_caching_policy_t caching_policy; -#ifdef HAVE_ATOMIC_OPS_H - AO_t cache_generation; -#else - uint32_t cache_generation; -#endif - unw_word_t dyn_generation; /* see dyn-common.h */ - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ - struct dwarf_rs_cache global_cache; - struct unw_debug_frame_list *debug_frames; - int validate; -}; - -struct cursor -{ - struct dwarf_cursor dwarf; /* must be first */ - - /* Format of sigcontext structure and address at which it is - stored: */ - enum - { - PPC_SCF_NONE, /* no signal frame encountered */ - PPC_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */ - } - sigcontext_format; - unw_word_t sigcontext_addr; -}; - -#define DWARF_GET_LOC(l) ((l).val) - -#ifdef UNW_LOCAL_ONLY -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) -# define DWARF_IS_REG_LOC(l) 0 -# define DWARF_IS_FP_LOC(l) 0 -# define DWARF_IS_V_LOC(l) 0 -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -#else /* !UNW_LOCAL_ONLY */ - -# define DWARF_LOC_TYPE_FP (1 << 0) -# define DWARF_LOC_TYPE_REG (1 << 1) -# define DWARF_LOC_TYPE_V (1 << 2) -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) \ - ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) -# define DWARF_IS_V_LOC(l) (((l).type & DWARF_LOC_TYPE_V) != 0) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_FP)) -# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_V)) - -#endif /* !UNW_LOCAL_ONLY */ - -static inline int -dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val) -{ - unw_word_t *valp = (unw_word_t *) val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - assert (DWARF_IS_V_LOC (loc)); - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - val, 0, c->as_arg); - - addr = DWARF_GET_LOC (loc); - - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp, - 0, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg); -} - -static inline int -dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - unw_word_t *valp = (unw_word_t *) & val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - assert (DWARF_IS_V_LOC (loc)); - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - &val, 1, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp, - 1, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg); -} - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val) -{ - unw_word_t *valp = (unw_word_t *) val; - unw_word_t addr; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - assert (DWARF_IS_FP_LOC (loc)); - assert (!DWARF_IS_V_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - val, 0, c->as_arg); - - addr = DWARF_GET_LOC (loc); - return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg); - -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - unw_word_t *valp = (unw_word_t *) & val; - unw_word_t addr; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - assert (DWARF_IS_FP_LOC (loc)); - assert (!DWARF_IS_V_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - &val, 1, c->as_arg); - - addr = DWARF_GET_LOC (loc); - - return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 1, c->as_arg); -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t * val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - assert (!DWARF_IS_V_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - assert (!DWARF_IS_V_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#define tdep_getcontext_trace unw_getcontext -#define tdep_init_done UNW_OBJ(init_done) -#define tdep_init UNW_OBJ(init) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table dwarf_search_unwind_table -#define tdep_find_unwind_table dwarf_find_unwind_table -#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#define tdep_fetch_frame(c,ip,n) do {} while(0) -#define tdep_cache_frame(c) 0 -#define tdep_reuse_frame(c,frame) do {} while(0) -#define tdep_stash_frame(c,rs) do {} while(0) -#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) -#define tdep_get_func_addr UNW_OBJ(get_func_addr) - -#ifdef UNW_LOCAL_ONLY -# define tdep_find_proc_info(c,ip,n) \ - dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - dwarf_put_unwind_info((as), (pi), (arg)) -#else -# define tdep_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - (*(as)->acc.put_unwind_info)((as), (pi), (arg)) -#endif - -extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip, - int need_unwind_info); - -#define tdep_get_as(c) ((c)->dwarf.as) -#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) -#define tdep_get_ip(c) ((c)->dwarf.ip) -#define tdep_big_endian(as) 1 - -extern int tdep_init_done; - -extern void tdep_init (void); -extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t * di, - unw_proc_info_t * pi, - int need_unwind_info, void *arg); -extern void *tdep_uc_addr (ucontext_t * uc, int reg); -extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, - unw_word_t * valp, int write); -extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, - unw_fpreg_t * valp, int write); -extern int tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr, - unw_word_t *entry_point); - -#endif /* PPC64_LIBUNWIND_I_H */ diff --git a/contrib/libunwind/include/tdep-ppc64/dwarf-config.h b/contrib/libunwind/include/tdep-ppc64/dwarf-config.h deleted file mode 100644 index 6d8ef0a9404..00000000000 --- a/contrib/libunwind/include/tdep-ppc64/dwarf-config.h +++ /dev/null @@ -1,56 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - - Copied from libunwind-x86_64.h, modified slightly for building - frysk successfully on ppc64, by Wu Zhou - Will be replaced when libunwind is ready on ppc64 platform. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_config_h -#define dwarf_config_h - -/* For PPC64, 48 GPRs + 33 FPRs + 33 AltiVec + 1 SPE */ -#define DWARF_NUM_PRESERVED_REGS 115 - -#define DWARF_REGNUM_MAP_LENGTH 115 - -/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) - -/* Convert a pointer to a dwarf_cursor structure to a pointer to - unw_cursor_t. */ -#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) - -typedef struct dwarf_loc - { - unw_word_t val; -#ifndef UNW_LOCAL_ONLY - unw_word_t type; /* see X86_LOC_TYPE_* macros. */ -#endif - } -dwarf_loc_t; - -#endif /* dwarf_config_h */ diff --git a/contrib/libunwind/include/tdep-ppc64/jmpbuf.h b/contrib/libunwind/include/tdep-ppc64/jmpbuf.h deleted file mode 100644 index 861e94d9712..00000000000 --- a/contrib/libunwind/include/tdep-ppc64/jmpbuf.h +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - - Copied from libunwind-x86_64.h, modified slightly for building - frysk successfully on ppc64, by Wu Zhou - Will be replaced when libunwind is ready on ppc64 platform. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -#define JB_SP 6 -#define JB_RP 7 -#define JB_MASK_SAVED 8 -#define JB_MASK 9 diff --git a/contrib/libunwind/include/tdep-ppc64/libunwind_i.h b/contrib/libunwind/include/tdep-ppc64/libunwind_i.h deleted file mode 100644 index 5c50ad63942..00000000000 --- a/contrib/libunwind/include/tdep-ppc64/libunwind_i.h +++ /dev/null @@ -1,370 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - - Copied from libunwind-x86_64.h, modified slightly for building - frysk successfully on ppc64, by Wu Zhou - Will be replaced when libunwind is ready on ppc64 platform. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef PPC64_LIBUNWIND_I_H -#define PPC64_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include -#include -#include - -#include "elf64.h" -#include "mempool.h" -#include "dwarf.h" - -typedef struct - { - /* no ppc64-specific fast trace */ - } -unw_tdep_frame_t; - -struct unw_addr_space -{ - struct unw_accessors acc; - int big_endian; - ppc64_abi_t abi; - unw_caching_policy_t caching_policy; -#ifdef HAVE_ATOMIC_OPS_H - AO_t cache_generation; -#else - uint32_t cache_generation; -#endif - unw_word_t dyn_generation; /* see dyn-common.h */ - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ - struct dwarf_rs_cache global_cache; - struct unw_debug_frame_list *debug_frames; - int validate; -}; - -struct cursor -{ - struct dwarf_cursor dwarf; /* must be first */ - - /* Format of sigcontext structure and address at which it is - stored: */ - enum - { - PPC_SCF_NONE, /* no signal frame encountered */ - PPC_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */ - } - sigcontext_format; - unw_word_t sigcontext_addr; -}; - -#define DWARF_GET_LOC(l) ((l).val) - -#ifdef UNW_LOCAL_ONLY -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) -# define DWARF_IS_REG_LOC(l) 0 -# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -# define DWARF_VREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) - -static inline int -dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_word_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_word_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ - -# define DWARF_LOC_TYPE_FP (1 << 0) -# define DWARF_LOC_TYPE_REG (1 << 1) -# define DWARF_LOC_TYPE_V (1 << 2) -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) \ - ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) -# define DWARF_IS_V_LOC(l) (((l).type & DWARF_LOC_TYPE_V) != 0) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_FP)) -# define DWARF_VREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_V)) - -static inline int -dwarf_getvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val) -{ - unw_word_t *valp = (unw_word_t *) val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - assert (DWARF_IS_V_LOC (loc)); - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - val, 0, c->as_arg); - - addr = DWARF_GET_LOC (loc); - - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp, - 0, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 0, c->as_arg); -} - -static inline int -dwarf_putvr (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - unw_word_t *valp = (unw_word_t *) & val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - assert (DWARF_IS_V_LOC (loc)); - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - &val, 1, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, valp, - 1, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 8, valp + 1, 1, c->as_arg); -} - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t * val) -{ - unw_word_t *valp = (unw_word_t *) val; - unw_word_t addr; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - assert (DWARF_IS_FP_LOC (loc)); - assert (!DWARF_IS_V_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - val, 0, c->as_arg); - - addr = DWARF_GET_LOC (loc); - return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 0, c->as_arg); - -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - unw_word_t *valp = (unw_word_t *) & val; - unw_word_t addr; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - assert (DWARF_IS_FP_LOC (loc)); - assert (!DWARF_IS_V_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - &val, 1, c->as_arg); - - addr = DWARF_GET_LOC (loc); - - return (*c->as->acc.access_mem) (c->as, addr + 0, valp, 1, c->as_arg); -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t * val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - assert (!DWARF_IS_V_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - assert (!DWARF_IS_V_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - -#define tdep_getcontext_trace unw_getcontext -#define tdep_init_done UNW_OBJ(init_done) -#define tdep_init UNW_OBJ(init) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table dwarf_search_unwind_table -#define tdep_find_unwind_table dwarf_find_unwind_table -#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#define tdep_fetch_frame(c,ip,n) do {} while(0) -#define tdep_cache_frame(c) 0 -#define tdep_reuse_frame(c,frame) do {} while(0) -#define tdep_stash_frame(c,rs) do {} while(0) -#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) -#define tdep_get_func_addr UNW_OBJ(get_func_addr) - -#ifdef UNW_LOCAL_ONLY -# define tdep_find_proc_info(c,ip,n) \ - dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - dwarf_put_unwind_info((as), (pi), (arg)) -#else -# define tdep_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - (*(as)->acc.put_unwind_info)((as), (pi), (arg)) -#endif - -extern int tdep_fetch_proc_info_post (struct dwarf_cursor *c, unw_word_t ip, - int need_unwind_info); - -#define tdep_get_as(c) ((c)->dwarf.as) -#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) -#define tdep_get_ip(c) ((c)->dwarf.ip) -#define tdep_big_endian(as) ((as)->big_endian) - -extern int tdep_init_done; - -extern void tdep_init (void); -extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t * di, - unw_proc_info_t * pi, - int need_unwind_info, void *arg); -extern void *tdep_uc_addr (ucontext_t * uc, int reg); -extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, - unw_word_t * valp, int write); -extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, - unw_fpreg_t * valp, int write); -extern int tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr, - unw_word_t *entry_point); - -#endif /* PPC64_LIBUNWIND_I_H */ diff --git a/contrib/libunwind/include/tdep-sh/dwarf-config.h b/contrib/libunwind/include/tdep-sh/dwarf-config.h deleted file mode 100644 index 2f76f5be7f4..00000000000 --- a/contrib/libunwind/include/tdep-sh/dwarf-config.h +++ /dev/null @@ -1,49 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_config_h -#define dwarf_config_h - -#define DWARF_NUM_PRESERVED_REGS 18 - -#define dwarf_to_unw_regnum(reg) (((reg) <= UNW_SH_PR) ? (reg) : 0) - -/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) - -/* Convert a pointer to a dwarf_cursor structure to a pointer to - unw_cursor_t. */ -#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) - -typedef struct dwarf_loc - { - unw_word_t val; -#ifndef UNW_LOCAL_ONLY - unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ -#endif - } -dwarf_loc_t; - -#endif /* dwarf_config_h */ diff --git a/contrib/libunwind/include/tdep-sh/jmpbuf.h b/contrib/libunwind/include/tdep-sh/jmpbuf.h deleted file mode 100644 index 8b44b5b219a..00000000000 --- a/contrib/libunwind/include/tdep-sh/jmpbuf.h +++ /dev/null @@ -1,48 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -/* SH4 glibc jump buffer contents: - * 0. r8 - * 1. r9 - * 2. r10 - * 3. r11 - * 4. r12 - * 5. r13 - * 6. r14 - * 7. r15 - * 8. pr/pc - * 9. gbr - * 10. fpscr - * 11. fr12 - * 12. fr13 - * 13. fr14 - * 14. fr15 - */ - -#define JB_SP 7 -#define JB_RP 8 -#define JB_MASK_SAVED 15 -#define JB_MASK 16 diff --git a/contrib/libunwind/include/tdep-sh/libunwind_i.h b/contrib/libunwind/include/tdep-sh/libunwind_i.h deleted file mode 100644 index 8ced49104b5..00000000000 --- a/contrib/libunwind/include/tdep-sh/libunwind_i.h +++ /dev/null @@ -1,280 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef SH_LIBUNWIND_I_H -#define SH_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include -#include - -#include "elf32.h" -#include "mempool.h" -#include "dwarf.h" - -typedef struct - { - /* no sh-specific fast trace */ - } -unw_tdep_frame_t; - -struct unw_addr_space - { - struct unw_accessors acc; - int big_endian; - unw_caching_policy_t caching_policy; -#ifdef HAVE_ATOMIC_OPS_H - AO_t cache_generation; -#else - uint32_t cache_generation; -#endif - unw_word_t dyn_generation; /* see dyn-common.h */ - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ - struct dwarf_rs_cache global_cache; - struct unw_debug_frame_list *debug_frames; - }; - -struct cursor - { - struct dwarf_cursor dwarf; /* must be first */ - enum - { - SH_SCF_NONE, /* no signal frame */ - SH_SCF_LINUX_SIGFRAME, /* non-RT signal frame */ - SH_SCF_LINUX_RT_SIGFRAME, /* RT signal frame */ - } - sigcontext_format; - unw_word_t sigcontext_addr; - unw_word_t sigcontext_sp; - unw_word_t sigcontext_pc; - }; - -#define DWARF_GET_LOC(l) ((l).val) - -#ifdef UNW_LOCAL_ONLY -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) -# define DWARF_IS_REG_LOC(l) 0 -# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_word_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_word_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ -# define DWARF_LOC_TYPE_FP (1 << 0) -# define DWARF_LOC_TYPE_REG (1 << 1) -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) \ - ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) -# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_FP)) - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - val, 0, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 0, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0, - c->as_arg); -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - &val, 1, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 1, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, - 1, c->as_arg); -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - -#define tdep_getcontext_trace unw_getcontext -#define tdep_init_done UNW_OBJ(init_done) -#define tdep_init UNW_OBJ(init) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table dwarf_search_unwind_table -#define tdep_find_unwind_table dwarf_find_unwind_table -#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#define tdep_fetch_frame(c,ip,n) do {} while(0) -#define tdep_cache_frame(c) 0 -#define tdep_reuse_frame(c,frame) do {} while(0) -#define tdep_stash_frame(c,rs) do {} while(0) -#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) - -#ifdef UNW_LOCAL_ONLY -# define tdep_find_proc_info(c,ip,n) \ - dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - dwarf_put_unwind_info((as), (pi), (arg)) -#else -# define tdep_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - (*(as)->acc.put_unwind_info)((as), (pi), (arg)) -#endif - -#define tdep_get_as(c) ((c)->dwarf.as) -#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) -#define tdep_get_ip(c) ((c)->dwarf.ip) -#define tdep_big_endian(as) ((as)->big_endian) - -extern int tdep_init_done; - -extern void tdep_init (void); -extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg); -extern void *tdep_uc_addr (unw_tdep_context_t *uc, int reg); -extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, - unw_word_t *valp, int write); -extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, - unw_fpreg_t *valp, int write); - -#endif /* SH_LIBUNWIND_I_H */ diff --git a/contrib/libunwind/include/tdep-tilegx/dwarf-config.h b/contrib/libunwind/include/tdep-tilegx/dwarf-config.h deleted file mode 100644 index 93bc6aaecce..00000000000 --- a/contrib/libunwind/include/tdep-tilegx/dwarf-config.h +++ /dev/null @@ -1,50 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_config_h -#define dwarf_config_h - -/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not - explicitly defined. */ -#define DWARF_NUM_PRESERVED_REGS 188 - -#define DWARF_REGNUM_MAP_LENGTH (56 + 2) - -/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) - -/* Convert a pointer to a dwarf_cursor structure to a pointer to - unw_cursor_t. */ -#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) - -typedef struct dwarf_loc -{ - unw_word_t val; -#ifndef UNW_LOCAL_ONLY - unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ -#endif -} dwarf_loc_t; - -#endif /* dwarf_config_h */ diff --git a/contrib/libunwind/include/tdep-tilegx/jmpbuf.h b/contrib/libunwind/include/tdep-tilegx/jmpbuf.h deleted file mode 100644 index 3afe9e46cc4..00000000000 --- a/contrib/libunwind/include/tdep-tilegx/jmpbuf.h +++ /dev/null @@ -1,33 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -/* FIXME for Tilegx! */ - -#define JB_SP 4 -#define JB_RP 5 -#define JB_MASK_SAVED 6 -#define JB_MASK 7 diff --git a/contrib/libunwind/include/tdep-tilegx/libunwind_i.h b/contrib/libunwind/include/tdep-tilegx/libunwind_i.h deleted file mode 100644 index 2cfed456a70..00000000000 --- a/contrib/libunwind/include/tdep-tilegx/libunwind_i.h +++ /dev/null @@ -1,263 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef TILEGX_LIBUNWIND_I_H -#define TILEGX_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include -#include - -# include "elf64.h" -#include "mempool.h" -#include "dwarf.h" - -typedef struct -{ - /* no Tilegx-specific fast trace */ -} unw_tdep_frame_t; - -struct unw_addr_space -{ - struct unw_accessors acc; - - int big_endian; - tilegx_abi_t abi; - unsigned int addr_size; - - unw_caching_policy_t caching_policy; -#ifdef HAVE_ATOMIC_OPS_H - AO_t cache_generation; -#else - uint32_t cache_generation; -#endif - unw_word_t dyn_generation; /* see dyn-common.h */ - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ - struct dwarf_rs_cache global_cache; - struct unw_debug_frame_list *debug_frames; -}; - -#define tdep_big_endian(as) ((as)->big_endian) - -struct cursor -{ - struct dwarf_cursor dwarf; /* must be first */ - unw_word_t sigcontext_addr; - unw_word_t sigcontext_sp; - unw_word_t sigcontext_pc; -}; - -#define DWARF_GET_LOC(l) ((l).val) - -#ifndef UNW_REMOTE_ONLY -typedef long tilegx_reg_t; -#endif - -#ifdef UNW_LOCAL_ONLY -#define DWARF_NULL_LOC DWARF_LOC (0, 0) -#define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -#define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) -#define DWARF_IS_REG_LOC(l) 0 -#define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -#define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -#define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) - -/* Tilegx has no FP. */ -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - Debug (1, "Tielgx has no fp!\n"); - abort(); - return 0; -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - Debug (1, "Tielgx has no fp!\n"); - abort(); - return 0; -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - - *val = *(tilegx_reg_t *) (intptr_t) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - - *(tilegx_reg_t *) (intptr_t) DWARF_GET_LOC (loc) = val; - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ -#define DWARF_LOC_TYPE_FP (1 << 0) -#define DWARF_LOC_TYPE_REG (1 << 1) -#define DWARF_NULL_LOC DWARF_LOC (0, 0) -#define DWARF_IS_NULL_LOC(l) \ - ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) -#define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -#define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -#define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) -#define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -#define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -#define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_FP)) - -/* TILEGX has no fp. */ -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - Debug (1, "Tielgx has no fp!\n"); - abort(); - return 0; -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - Debug (1, "Tielgx has no fp!\n"); - abort(); - return 0; -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); - - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - -#define tdep_getcontext_trace unw_getcontext -#define tdep_init_done UNW_OBJ(init_done) -#define tdep_needs_initialization UNW_OBJ(needs_initialization) -#define tdep_init UNW_OBJ(init) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table dwarf_search_unwind_table -#define tdep_find_unwind_table dwarf_find_unwind_table -#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#define tdep_fetch_frame(c,ip,n) do {} while(0) -#define tdep_cache_frame(c) 0 -#define tdep_reuse_frame(c,frame) do {} while(0) -#define tdep_stash_frame(c,rs) do {} while(0) -#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) - -#ifdef UNW_LOCAL_ONLY -#define tdep_find_proc_info(c,ip,n) \ - dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -#define tdep_put_unwind_info(as,pi,arg) \ - dwarf_put_unwind_info((as), (pi), (arg)) -#else -#define tdep_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -#define tdep_put_unwind_info(as,pi,arg) \ - (*(as)->acc.put_unwind_info)((as), (pi), (arg)) -#endif - -#define tdep_get_as(c) ((c)->dwarf.as) -#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) -#define tdep_get_ip(c) ((c)->dwarf.ip) - -extern int tdep_init_done; - -extern void tdep_init (void); -extern int tdep_search_unwind_table (unw_addr_space_t as, - unw_word_t ip, - unw_dyn_info_t *di, - unw_proc_info_t *pi, - int need_unwind_info, - void *arg); -extern void *tdep_uc_addr (ucontext_t *uc, int reg); -extern int tdep_get_elf_image (struct elf_image *ei, - pid_t pid, unw_word_t ip, - unsigned long *segbase, - unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, - unw_regnum_t reg, - unw_word_t *valp, - int write); -extern int tdep_access_fpreg (struct cursor *c, - unw_regnum_t reg, - unw_fpreg_t *valp, - int write); - -#endif /* TILEGX_LIBUNWIND_I_H */ diff --git a/contrib/libunwind/include/tdep-x86/dwarf-config.h b/contrib/libunwind/include/tdep-x86/dwarf-config.h deleted file mode 100644 index f76f9c1c4eb..00000000000 --- a/contrib/libunwind/include/tdep-x86/dwarf-config.h +++ /dev/null @@ -1,52 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_config_h -#define dwarf_config_h - -/* This matches the value used by GCC (see - gcc/config/i386.h:DWARF_FRAME_REGISTERS), which leaves plenty of - room for expansion. */ -#define DWARF_NUM_PRESERVED_REGS 17 - -#define DWARF_REGNUM_MAP_LENGTH 19 - -/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) 0 - -/* Convert a pointer to a dwarf_cursor structure to a pointer to - unw_cursor_t. */ -#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) - -typedef struct dwarf_loc - { - unw_word_t val; -#ifndef UNW_LOCAL_ONLY - unw_word_t type; /* see X86_LOC_TYPE_* macros. */ -#endif - } -dwarf_loc_t; - -#endif /* dwarf_config_h */ diff --git a/contrib/libunwind/include/tdep-x86/jmpbuf.h b/contrib/libunwind/include/tdep-x86/jmpbuf.h deleted file mode 100644 index 521dfa6992b..00000000000 --- a/contrib/libunwind/include/tdep-x86/jmpbuf.h +++ /dev/null @@ -1,42 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -#if defined __linux__ - -#define JB_SP 4 -#define JB_RP 5 -#define JB_MASK_SAVED 6 -#define JB_MASK 7 - -#elif defined __FreeBSD__ - -#define JB_SP 2 -#define JB_RP 0 -#define JB_MASK_SAVED 11 -#define JB_MASK 7 - -#endif diff --git a/contrib/libunwind/include/tdep-x86/libunwind_i.h b/contrib/libunwind/include/tdep-x86/libunwind_i.h deleted file mode 100644 index 5231189a499..00000000000 --- a/contrib/libunwind/include/tdep-x86/libunwind_i.h +++ /dev/null @@ -1,293 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef X86_LIBUNWIND_I_H -#define X86_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include -#include - -#include "elf32.h" -#include "mempool.h" -#include "dwarf.h" - -typedef struct - { - /* no x86-specific fast trace */ - } -unw_tdep_frame_t; - -struct unw_addr_space - { - struct unw_accessors acc; - unw_caching_policy_t caching_policy; -#ifdef HAVE_ATOMIC_OPS_H - AO_t cache_generation; -#else - uint32_t cache_generation; -#endif - unw_word_t dyn_generation; /* see dyn-common.h */ - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ - struct dwarf_rs_cache global_cache; - struct unw_debug_frame_list *debug_frames; - }; - -struct cursor - { - struct dwarf_cursor dwarf; /* must be first */ - - /* Format of sigcontext structure and address at which it is - stored: */ - enum - { - X86_SCF_NONE, /* no signal frame encountered */ - X86_SCF_LINUX_SIGFRAME, /* Linux x86 sigcontext */ - X86_SCF_LINUX_RT_SIGFRAME, /* POSIX ucontext_t */ - X86_SCF_FREEBSD_SIGFRAME, /* FreeBSD x86 sigcontext */ - X86_SCF_FREEBSD_SIGFRAME4, /* FreeBSD 4.x x86 sigcontext */ - X86_SCF_FREEBSD_OSIGFRAME, /* FreeBSD pre-4.x x86 sigcontext */ - X86_SCF_FREEBSD_SYSCALL, /* FreeBSD x86 syscall */ - } - sigcontext_format; - unw_word_t sigcontext_addr; - int validate; - ucontext_t *uc; - }; - -static inline ucontext_t * -dwarf_get_uc(const struct dwarf_cursor *cursor) -{ - const struct cursor *c = (struct cursor *) cursor->as_arg; - return c->uc; -} - -#define DWARF_GET_LOC(l) ((l).val) - -#ifdef UNW_LOCAL_ONLY -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) -# define DWARF_IS_REG_LOC(l) 0 -# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr(dwarf_get_uc(c), (r)), 0)) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - tdep_uc_addr(dwarf_get_uc(c), (r)), 0)) - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_fpreg_t *) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_fpreg_t *) DWARF_GET_LOC (loc) = val; - return 0; -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#else /* !UNW_LOCAL_ONLY */ -# define DWARF_LOC_TYPE_FP (1 << 0) -# define DWARF_LOC_TYPE_REG (1 << 1) -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) \ - ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) -# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_FP)) - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - val, 0, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 0, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0, - c->as_arg); -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - &val, 1, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 1, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, - 1, c->as_arg); -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - -#define tdep_getcontext_trace unw_getcontext -#define tdep_init_done UNW_OBJ(init_done) -#define tdep_init UNW_OBJ(init) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table dwarf_search_unwind_table -#define tdep_find_unwind_table dwarf_find_unwind_table -#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#define tdep_fetch_frame(c,ip,n) do {} while(0) -#define tdep_cache_frame(c) 0 -#define tdep_reuse_frame(c,frame) do {} while(0) -#define tdep_stash_frame(c,rs) do {} while(0) -#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) - -#ifdef UNW_LOCAL_ONLY -# define tdep_find_proc_info(c,ip,n) \ - dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - dwarf_put_unwind_info((as), (pi), (arg)) -#else -# define tdep_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - (*(as)->acc.put_unwind_info)((as), (pi), (arg)) -#endif - -#define tdep_get_as(c) ((c)->dwarf.as) -#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) -#define tdep_get_ip(c) ((c)->dwarf.ip) -#define tdep_big_endian(as) 0 - -extern int tdep_init_done; - -extern void tdep_init (void); -extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg); -extern void *tdep_uc_addr (ucontext_t *uc, int reg); -extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, - unw_word_t *valp, int write); -extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, - unw_fpreg_t *valp, int write); - -#endif /* X86_LIBUNWIND_I_H */ diff --git a/contrib/libunwind/include/tdep-x86_64/dwarf-config.h b/contrib/libunwind/include/tdep-x86_64/dwarf-config.h deleted file mode 100644 index ff77808e069..00000000000 --- a/contrib/libunwind/include/tdep-x86_64/dwarf-config.h +++ /dev/null @@ -1,57 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* copy of include/tdep-x86/dwarf-config.h, modified slightly for x86-64 - some consolidation is possible here */ - -#ifndef dwarf_config_h -#define dwarf_config_h - -/* XXX need to verify if this value is correct */ -#ifdef CONFIG_MSABI_SUPPORT -#define DWARF_NUM_PRESERVED_REGS 33 -#else -#define DWARF_NUM_PRESERVED_REGS 17 -#endif - -#define DWARF_REGNUM_MAP_LENGTH DWARF_NUM_PRESERVED_REGS - -/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) 0 - -/* Convert a pointer to a dwarf_cursor structure to a pointer to - unw_cursor_t. */ -#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) - -typedef struct dwarf_loc - { - unw_word_t val; - unw_word_t type; /* see X86_LOC_TYPE_* macros. */ - } -dwarf_loc_t; - -#endif /* dwarf_config_h */ diff --git a/contrib/libunwind/include/tdep-x86_64/jmpbuf.h b/contrib/libunwind/include/tdep-x86_64/jmpbuf.h deleted file mode 100644 index d57196676db..00000000000 --- a/contrib/libunwind/include/tdep-x86_64/jmpbuf.h +++ /dev/null @@ -1,43 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#if defined __linux__ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -#define JB_SP 6 -#define JB_RP 7 -#define JB_MASK_SAVED 8 -#define JB_MASK 9 - -#elif defined __FreeBSD__ - -#define JB_SP 2 -#define JB_RP 0 -/* Pretend the ip cannot be 0 and mask is always saved */ -#define JB_MASK_SAVED 0 -#define JB_MASK 9 - -#endif diff --git a/contrib/libunwind/include/tdep-x86_64/libunwind_i.h b/contrib/libunwind/include/tdep-x86_64/libunwind_i.h deleted file mode 100644 index 283525c16a3..00000000000 --- a/contrib/libunwind/include/tdep-x86_64/libunwind_i.h +++ /dev/null @@ -1,264 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef X86_64_LIBUNWIND_I_H -#define X86_64_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include -#include - -#include "elf64.h" -#include "mempool.h" -#include "dwarf.h" - -typedef enum - { - UNW_X86_64_FRAME_ALIGNED = -3, /* frame stack pointer aligned */ - UNW_X86_64_FRAME_STANDARD = -2, /* regular rbp, rsp +/- offset */ - UNW_X86_64_FRAME_SIGRETURN = -1, /* special sigreturn frame */ - UNW_X86_64_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */ - UNW_X86_64_FRAME_GUESSED = 1 /* guessed it was regular, but not known */ - } -unw_tdep_frame_type_t; - -typedef struct - { - uint64_t virtual_address; - int64_t frame_type : 3; /* unw_tdep_frame_type_t classification */ - int64_t last_frame : 1; /* non-zero if last frame in chain */ - int64_t cfa_reg_rsp : 1; /* cfa dwarf base register is rsp vs. rbp */ - int64_t cfa_reg_offset : 29; /* cfa is at this offset from base register value */ - int64_t rbp_cfa_offset : 15; /* rbp saved at this offset from cfa (-1 = not saved) */ - int64_t rsp_cfa_offset : 15; /* rsp saved at this offset from cfa (-1 = not saved) */ - } -unw_tdep_frame_t; - -struct unw_addr_space - { - struct unw_accessors acc; - unw_caching_policy_t caching_policy; -#ifdef HAVE_ATOMIC_OPS_H - AO_t cache_generation; -#else - uint32_t cache_generation; -#endif - unw_word_t dyn_generation; /* see dyn-common.h */ - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ - struct dwarf_rs_cache global_cache; - struct unw_debug_frame_list *debug_frames; - }; - -struct cursor - { - struct dwarf_cursor dwarf; /* must be first */ - - unw_tdep_frame_t frame_info; /* quick tracing assist info */ - - /* Format of sigcontext structure and address at which it is - stored: */ - enum - { - X86_64_SCF_NONE, /* no signal frame encountered */ - X86_64_SCF_LINUX_RT_SIGFRAME, /* Linux ucontext_t */ - X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD signal frame */ - X86_64_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall */ - } - sigcontext_format; - unw_word_t sigcontext_addr; - int validate; - ucontext_t *uc; - }; - -static inline ucontext_t * -dwarf_get_uc(const struct dwarf_cursor *cursor) -{ - const struct cursor *c = (struct cursor *) cursor->as_arg; - return c->uc; -} - -#define DWARF_GET_LOC(l) ((l).val) -# define DWARF_LOC_TYPE_MEM (0 << 0) -# define DWARF_LOC_TYPE_FP (1 << 0) -# define DWARF_LOC_TYPE_REG (1 << 1) -# define DWARF_LOC_TYPE_VAL (1 << 2) - -# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) -# define DWARF_IS_MEM_LOC(l) ((l).type == DWARF_LOC_TYPE_MEM) -# define DWARF_IS_VAL_LOC(l) (((l).type & DWARF_LOC_TYPE_VAL) != 0) - -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -# define DWARF_VAL_LOC(c,v) DWARF_LOC ((v), DWARF_LOC_TYPE_VAL) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), DWARF_LOC_TYPE_MEM) - -#ifdef UNW_LOCAL_ONLY -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - x86_64_r_uc_addr(dwarf_get_uc(c), (r)), 0)) -# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \ - x86_64_r_uc_addr(dwarf_get_uc(c), (r)), 0)) - -#else /* !UNW_LOCAL_ONLY */ - -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) \ - ({ dwarf_loc_t _l = (l); _l.val == 0 && _l.type == 0; }) -# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_FP)) - -#endif /* !UNW_LOCAL_ONLY */ - -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - abort (); -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - abort (); -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - if (DWARF_IS_MEM_LOC (loc)) - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - assert(DWARF_IS_VAL_LOC (loc)); - *val = DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - assert(!DWARF_IS_VAL_LOC (loc)); - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#define tdep_getcontext_trace UNW_ARCH_OBJ(getcontext_trace) -#define tdep_init_done UNW_OBJ(init_done) -#define tdep_init_mem_validate UNW_OBJ(init_mem_validate) -#define tdep_init UNW_OBJ(init) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table dwarf_search_unwind_table -#define tdep_find_unwind_table dwarf_find_unwind_table -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#if __linux__ -# define tdep_fetch_frame UNW_OBJ(fetch_frame) -# define tdep_cache_frame UNW_OBJ(cache_frame) -# define tdep_reuse_frame UNW_OBJ(reuse_frame) -#else -# define tdep_fetch_frame(c,ip,n) do {} while(0) -# define tdep_cache_frame(c) 0 -# define tdep_reuse_frame(c,frame) do {} while(0) -#endif -#define tdep_stash_frame UNW_OBJ(stash_frame) -#define tdep_trace UNW_OBJ(tdep_trace) -#define x86_64_r_uc_addr UNW_OBJ(r_uc_addr) - -#ifdef UNW_LOCAL_ONLY -# define tdep_find_proc_info(c,ip,n) \ - dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - dwarf_put_unwind_info((as), (pi), (arg)) -#else -# define tdep_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - (*(as)->acc.put_unwind_info)((as), (pi), (arg)) -#endif - -#define tdep_get_as(c) ((c)->dwarf.as) -#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) -#define tdep_get_ip(c) ((c)->dwarf.ip) -#define tdep_big_endian(as) 0 - -extern int tdep_init_done; - -extern void tdep_init (void); -extern void tdep_init_mem_validate (void); -extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg); -extern void *x86_64_r_uc_addr (ucontext_t *uc, int reg); -extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, - unw_word_t *valp, int write); -extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, - unw_fpreg_t *valp, int write); -#if __linux__ -extern void tdep_fetch_frame (struct dwarf_cursor *c, unw_word_t ip, - int need_unwind_info); -extern int tdep_cache_frame (struct dwarf_cursor *c); -extern void tdep_reuse_frame (struct dwarf_cursor *c, - int frame); -extern void tdep_stash_frame (struct dwarf_cursor *c, - struct dwarf_reg_state *rs); -#endif - -extern int tdep_getcontext_trace (unw_tdep_context_t *); -extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n); - -#endif /* X86_64_LIBUNWIND_I_H */ diff --git a/contrib/libunwind/include/tdep/dwarf-config.h b/contrib/libunwind/include/tdep/dwarf-config.h deleted file mode 100644 index c759a46c63b..00000000000 --- a/contrib/libunwind/include/tdep/dwarf-config.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Provide a real file - not a symlink - as it would cause multiarch conflicts - when multiple different arch releases are installed simultaneously. */ - -#if defined __aarch64__ -# include "tdep-aarch64/dwarf-config.h" -#elif defined __arm__ -# include "tdep-arm/dwarf-config.h" -#elif defined __hppa__ -# include "tdep-hppa/dwarf-config.h" -#elif defined __ia64__ -# include "tdep-ia64/dwarf-config.h" -#elif defined __mips__ -# include "tdep-mips/dwarf-config.h" -#elif defined __powerpc__ && !defined __powerpc64__ -# include "tdep-ppc32/dwarf-config.h" -#elif defined __powerpc64__ -# include "tdep-ppc64/dwarf-config.h" -#elif defined __sh__ -# include "tdep-sh/dwarf-config.h" -#elif defined __i386__ -# include "tdep-x86/dwarf-config.h" -#elif defined __x86_64__ || defined __amd64__ -# include "tdep-x86_64/dwarf-config.h" -#elif defined __tilegx__ -# include "tdep-tilegx/dwarf-config.h" -#else -# error "Unsupported arch" -#endif diff --git a/contrib/libunwind/include/tdep/jmpbuf.h b/contrib/libunwind/include/tdep/jmpbuf.h deleted file mode 100644 index 13093a0cdc3..00000000000 --- a/contrib/libunwind/include/tdep/jmpbuf.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Provide a real file - not a symlink - as it would cause multiarch conflicts - when multiple different arch releases are installed simultaneously. */ - -#ifndef UNW_REMOTE_ONLY - -#if defined __aarch64__ -# include "tdep-aarch64/jmpbuf.h" -#elif defined __arm__ -# include "tdep-arm/jmpbuf.h" -#elif defined __hppa__ -# include "tdep-hppa/jmpbuf.h" -#elif defined __ia64__ -# include "tdep-ia64/jmpbuf.h" -#elif defined __mips__ -# include "tdep-mips/jmpbuf.h" -#elif defined __powerpc__ && !defined __powerpc64__ -# include "tdep-ppc32/jmpbuf.h" -#elif defined __powerpc64__ -# include "tdep-ppc64/jmpbuf.h" -#elif defined __i386__ -# include "tdep-x86/jmpbuf.h" -#elif defined __x86_64__ -# include "tdep-x86_64/jmpbuf.h" -#elif defined __tilegx__ -# include "tdep-tilegx/jmpbuf.h" -#else -# error "Unsupported arch" -#endif - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/include/tdep/libunwind_i.h.in b/contrib/libunwind/include/tdep/libunwind_i.h.in deleted file mode 100644 index af05a7fba24..00000000000 --- a/contrib/libunwind/include/tdep/libunwind_i.h.in +++ /dev/null @@ -1,37 +0,0 @@ -/* Provide a real file - not a symlink - as it would cause multiarch conflicts - when multiple different arch releases are installed simultaneously. */ - -#ifndef UNW_REMOTE_ONLY - -#if defined __aarch64__ -# include "tdep-aarch64/libunwind_i.h" -#elif defined __arm__ -# include "tdep-arm/libunwind_i.h" -#elif defined __hppa__ -# include "tdep-hppa/libunwind_i.h" -#elif defined __ia64__ -# include "tdep-ia64/libunwind_i.h" -#elif defined __mips__ -# include "tdep-mips/libunwind_i.h" -#elif defined __powerpc__ && !defined __powerpc64__ -# include "tdep-ppc32/libunwind_i.h" -#elif defined __powerpc64__ -# include "tdep-ppc64/libunwind_i.h" -#elif defined __sh__ -# include "tdep-sh/libunwind_i.h" -#elif defined __i386__ -# include "tdep-x86/libunwind_i.h" -#elif defined __x86_64__ -# include "tdep-x86_64/libunwind_i.h" -#elif defined __tilegx__ -# include "tdep-tilegx/libunwind_i.h" -#else -# error "Unsupported arch" -#endif - - -#else /* UNW_REMOTE_ONLY */ - -# include "tdep-@arch@/libunwind_i.h" - -#endif /* UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/include/unwind.h b/contrib/libunwind/include/unwind.h deleted file mode 100644 index 7cf128deca3..00000000000 --- a/contrib/libunwind/include/unwind.h +++ /dev/null @@ -1,154 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _UNWIND_H -#define _UNWIND_H - -/* For uint64_t */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Minimal interface as per C++ ABI draft standard: - - http://www.codesourcery.com/cxx-abi/abi-eh.html */ - -typedef enum - { - _URC_NO_REASON = 0, - _URC_FOREIGN_EXCEPTION_CAUGHT = 1, - _URC_FATAL_PHASE2_ERROR = 2, - _URC_FATAL_PHASE1_ERROR = 3, - _URC_NORMAL_STOP = 4, - _URC_END_OF_STACK = 5, - _URC_HANDLER_FOUND = 6, - _URC_INSTALL_CONTEXT = 7, - _URC_CONTINUE_UNWIND = 8 - } -_Unwind_Reason_Code; - -typedef int _Unwind_Action; - -#define _UA_SEARCH_PHASE 1 -#define _UA_CLEANUP_PHASE 2 -#define _UA_HANDLER_FRAME 4 -#define _UA_FORCE_UNWIND 8 - -struct _Unwind_Context; /* opaque data-structure */ -struct _Unwind_Exception; /* forward-declaration */ - -typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, - struct _Unwind_Exception *); - -typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) (int, _Unwind_Action, - uint64_t, - struct _Unwind_Exception *, - struct _Unwind_Context *, - void *); - -/* The C++ ABI requires exception_class, private_1, and private_2 to - be of type uint64 and the entire structure to be - double-word-aligned. Please note that exception_class stays 64-bit - even on 32-bit machines for gcc compatibility. */ -struct _Unwind_Exception - { - uint64_t exception_class; - _Unwind_Exception_Cleanup_Fn exception_cleanup; - unsigned long private_1; - unsigned long private_2; - } __attribute__((__aligned__)); - -extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *); -extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *, - _Unwind_Stop_Fn, void *); -extern void _Unwind_Resume (struct _Unwind_Exception *); -extern void _Unwind_DeleteException (struct _Unwind_Exception *); -extern unsigned long _Unwind_GetGR (struct _Unwind_Context *, int); -extern void _Unwind_SetGR (struct _Unwind_Context *, int, unsigned long); -extern unsigned long _Unwind_GetIP (struct _Unwind_Context *); -extern unsigned long _Unwind_GetIPInfo (struct _Unwind_Context *, int *); -extern void _Unwind_SetIP (struct _Unwind_Context *, unsigned long); -extern unsigned long _Unwind_GetLanguageSpecificData (struct _Unwind_Context*); -extern unsigned long _Unwind_GetRegionStart (struct _Unwind_Context *); - -#ifdef _GNU_SOURCE - -/* Callback for _Unwind_Backtrace(). The backtrace stops immediately - if the callback returns any value other than _URC_NO_REASON. */ -typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *, - void *); - -/* See http://gcc.gnu.org/ml/gcc-patches/2001-09/msg00082.html for why - _UA_END_OF_STACK exists. */ -# define _UA_END_OF_STACK 16 - -/* If the unwind was initiated due to a forced unwind, resume that - operation, else re-raise the exception. This is used by - __cxa_rethrow(). */ -extern _Unwind_Reason_Code - _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *); - -/* See http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00154.html for why - _Unwind_GetBSP() exists. */ -extern unsigned long _Unwind_GetBSP (struct _Unwind_Context *); - -/* Return the "canonical frame address" for the given context. - This is used by NPTL... */ -extern unsigned long _Unwind_GetCFA (struct _Unwind_Context *); - -/* Return the base-address for data references. */ -extern unsigned long _Unwind_GetDataRelBase (struct _Unwind_Context *); - -/* Return the base-address for text references. */ -extern unsigned long _Unwind_GetTextRelBase (struct _Unwind_Context *); - -/* Call _Unwind_Trace_Fn once for each stack-frame, without doing any - cleanup. The first frame for which the callback is invoked is the - one for the caller of _Unwind_Backtrace(). _Unwind_Backtrace() - returns _URC_END_OF_STACK when the backtrace stopped due to - reaching the end of the call-chain or _URC_FATAL_PHASE1_ERROR if it - stops for any other reason. */ -extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); - -/* Find the start-address of the procedure containing the specified IP - or NULL if it cannot be found (e.g., because the function has no - unwind info). Note: there is not necessarily a one-to-one - correspondence between source-level functions and procedures: some - functions don't have unwind-info and others are split into multiple - procedures. */ -extern void *_Unwind_FindEnclosingFunction (void *); - -/* See also Linux Standard Base Spec: - http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/libgcc-s.html */ - -#endif /* _GNU_SOURCE */ - -#ifdef __cplusplus -}; -#endif - -#endif /* _UNWIND_H */ diff --git a/contrib/libunwind/include/x86/jmpbuf.h b/contrib/libunwind/include/x86/jmpbuf.h deleted file mode 100644 index 94d5984f08c..00000000000 --- a/contrib/libunwind/include/x86/jmpbuf.h +++ /dev/null @@ -1,31 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -#define JB_SP 4 -#define JB_RP 5 -#define JB_MASK_SAVED 6 -#define JB_MASK 7 diff --git a/contrib/libunwind/src/Makefile.am b/contrib/libunwind/src/Makefile.am deleted file mode 100644 index 7514ab551aa..00000000000 --- a/contrib/libunwind/src/Makefile.am +++ /dev/null @@ -1,749 +0,0 @@ -SOVERSION=8:1:0 # See comments at end of file. -SETJMP_SO_VERSION=0:0:0 -COREDUMP_SO_VERSION=0:0:0 -# -# Don't link with start-files since we don't use any constructors/destructors: -# -COMMON_SO_LDFLAGS = $(LDFLAGS_NOSTARTFILES) - -lib_LIBRARIES = -lib_LTLIBRARIES = -if !REMOTE_ONLY -lib_LTLIBRARIES += libunwind.la -if BUILD_PTRACE -lib_LTLIBRARIES += libunwind-ptrace.la -endif -if BUILD_COREDUMP -lib_LTLIBRARIES += libunwind-coredump.la -endif -endif - -noinst_HEADERS = -noinst_LTLIBRARIES = - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libunwind-generic.pc - -if !REMOTE_ONLY -pkgconfig_DATA += unwind/libunwind.pc -endif - -if BUILD_PTRACE -pkgconfig_DATA += ptrace/libunwind-ptrace.pc -endif - -if BUILD_SETJMP -pkgconfig_DATA += setjmp/libunwind-setjmp.pc -endif - -if BUILD_COREDUMP -pkgconfig_DATA += coredump/libunwind-coredump.pc -endif - -### libunwind-ptrace: -libunwind_ptrace_la_SOURCES = \ - ptrace/_UPT_elf.c \ - ptrace/_UPT_accessors.c ptrace/_UPT_access_fpreg.c \ - ptrace/_UPT_access_mem.c ptrace/_UPT_access_reg.c \ - ptrace/_UPT_create.c ptrace/_UPT_destroy.c \ - ptrace/_UPT_find_proc_info.c ptrace/_UPT_get_dyn_info_list_addr.c \ - ptrace/_UPT_put_unwind_info.c ptrace/_UPT_get_proc_name.c \ - ptrace/_UPT_reg_offset.c ptrace/_UPT_resume.c -noinst_HEADERS += ptrace/_UPT_internal.h - -### libunwind-coredump: -libunwind_coredump_la_SOURCES = \ - coredump/_UCD_accessors.c \ - coredump/_UCD_create.c \ - coredump/_UCD_destroy.c \ - coredump/_UCD_access_mem.c \ - coredump/_UCD_elf_map_image.c \ - coredump/_UCD_find_proc_info.c \ - coredump/_UCD_get_proc_name.c \ - \ - coredump/_UPT_elf.c \ - coredump/_UPT_access_fpreg.c \ - coredump/_UPT_get_dyn_info_list_addr.c \ - coredump/_UPT_put_unwind_info.c \ - coredump/_UPT_resume.c -libunwind_coredump_la_LDFLAGS = $(COMMON_SO_LDFLAGS) \ - -version-info $(COREDUMP_SO_VERSION) -libunwind_coredump_la_LIBADD = $(LIBLZMA) -noinst_HEADERS += coredump/_UCD_internal.h coredump/_UCD_lib.h - -### libunwind-setjmp: -libunwind_setjmp_la_LDFLAGS = $(COMMON_SO_LDFLAGS) \ - -version-info $(SETJMP_SO_VERSION) - -if USE_ELF32 -LIBUNWIND_ELF = libunwind-elf32.la -endif -if USE_ELF64 -LIBUNWIND_ELF = libunwind-elf64.la -endif -if USE_ELFXX -LIBUNWIND_ELF = libunwind-elfxx.la -endif - -libunwind_setjmp_la_LIBADD = $(LIBUNWIND_ELF) \ - libunwind-$(arch).la \ - libunwind.la -lc -libunwind_setjmp_la_SOURCES = setjmp/longjmp.c \ - setjmp/siglongjmp.c -noinst_HEADERS += setjmp/setjmp_i.h - -### libunwind: -libunwind_la_LIBADD = - -# List of arch-independent files needed by both local-only and generic -# libraries: -libunwind_la_SOURCES_common = \ - $(libunwind_la_SOURCES_os) \ - mi/init.c mi/flush_cache.c mi/mempool.c mi/strerror.c - -# List of arch-independent files needed by generic library (libunwind-$ARCH): -libunwind_la_SOURCES_generic = \ - mi/Gdyn-extract.c mi/Gdyn-remote.c mi/Gfind_dynamic_proc_info.c \ - mi/Gget_accessors.c \ - mi/Gget_proc_info_by_ip.c mi/Gget_proc_name.c \ - mi/Gput_dynamic_unwind_info.c mi/Gdestroy_addr_space.c \ - mi/Gget_reg.c mi/Gset_reg.c \ - mi/Gget_fpreg.c mi/Gset_fpreg.c \ - mi/Gset_caching_policy.c \ - mi/Gset_cache_size.c - -if SUPPORT_CXX_EXCEPTIONS -libunwind_la_SOURCES_local_unwind = \ - unwind/Backtrace.c unwind/DeleteException.c \ - unwind/FindEnclosingFunction.c unwind/ForcedUnwind.c \ - unwind/GetBSP.c unwind/GetCFA.c unwind/GetDataRelBase.c \ - unwind/GetGR.c unwind/GetIP.c unwind/GetLanguageSpecificData.c \ - unwind/GetRegionStart.c unwind/GetTextRelBase.c \ - unwind/RaiseException.c unwind/Resume.c \ - unwind/Resume_or_Rethrow.c unwind/SetGR.c unwind/SetIP.c \ - unwind/GetIPInfo.c - -# _ReadULEB()/_ReadSLEB() are needed for Intel C++ 8.0 compatibility -libunwind_la_SOURCES_os_linux_local = mi/_ReadULEB.c mi/_ReadSLEB.c -endif - -# List of arch-independent files needed by local-only library (libunwind): -libunwind_la_SOURCES_local_nounwind = \ - $(libunwind_la_SOURCES_os_local) \ - mi/backtrace.c \ - mi/dyn-cancel.c mi/dyn-info-list.c mi/dyn-register.c \ - mi/Ldyn-extract.c mi/Lfind_dynamic_proc_info.c \ - mi/Lget_accessors.c \ - mi/Lget_proc_info_by_ip.c mi/Lget_proc_name.c \ - mi/Lput_dynamic_unwind_info.c mi/Ldestroy_addr_space.c \ - mi/Lget_reg.c mi/Lset_reg.c \ - mi/Lget_fpreg.c mi/Lset_fpreg.c \ - mi/Lset_caching_policy.c \ - mi/Lset_cache_size.c - -libunwind_la_SOURCES_local = \ - $(libunwind_la_SOURCES_local_nounwind) \ - $(libunwind_la_SOURCES_local_unwind) - -noinst_HEADERS += os-linux.h -libunwind_la_SOURCES_os_linux = os-linux.c - -libunwind_la_SOURCES_os_hpux = os-hpux.c - -libunwind_la_SOURCES_os_freebsd = os-freebsd.c - -libunwind_la_SOURCES_os_qnx = os-qnx.c - -libunwind_dwarf_common_la_SOURCES = dwarf/global.c - -libunwind_dwarf_local_la_SOURCES = \ - dwarf/Lexpr.c dwarf/Lfde.c dwarf/Lparser.c dwarf/Lpe.c \ - dwarf/Lfind_proc_info-lsb.c \ - dwarf/Lfind_unwind_table.c -libunwind_dwarf_local_la_LIBADD = libunwind-dwarf-common.la - -libunwind_dwarf_generic_la_SOURCES = \ - dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c \ - dwarf/Gfind_proc_info-lsb.c \ - dwarf/Gfind_unwind_table.c -libunwind_dwarf_generic_la_LIBADD = libunwind-dwarf-common.la - -if USE_DWARF - noinst_LTLIBRARIES += libunwind-dwarf-common.la libunwind-dwarf-generic.la -if !REMOTE_ONLY - noinst_LTLIBRARIES += libunwind-dwarf-local.la -endif - libunwind_la_LIBADD += libunwind-dwarf-local.la -endif - -noinst_HEADERS += elf32.h elf64.h elfxx.h - -libunwind_elf32_la_SOURCES = elf32.c -libunwind_elf64_la_SOURCES = elf64.c -libunwind_elfxx_la_SOURCES = elfxx.c -libunwind_elf32_la_LIBADD = $(LIBLZMA) -libunwind_elf64_la_LIBADD = $(LIBLZMA) -libunwind_elfxx_la_LIBADD = $(LIBLZMA) - -noinst_LTLIBRARIES += $(LIBUNWIND_ELF) -libunwind_la_LIBADD += $(LIBUNWIND_ELF) - -# The list of files that go into libunwind and libunwind-aarch64: -noinst_HEADERS += aarch64/init.h aarch64/offsets.h aarch64/unwind_i.h -libunwind_la_SOURCES_aarch64_common = $(libunwind_la_SOURCES_common) \ - aarch64/is_fpreg.c aarch64/regname.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_aarch64 = $(libunwind_la_SOURCES_aarch64_common) \ - $(libunwind_la_SOURCES_local) \ - aarch64/Lapply_reg_state.c aarch64/Lreg_states_iterate.c \ - aarch64/Lcreate_addr_space.c aarch64/Lget_proc_info.c \ - aarch64/Lget_save_loc.c aarch64/Lglobal.c aarch64/Linit.c \ - aarch64/Linit_local.c aarch64/Linit_remote.c \ - aarch64/Lis_signal_frame.c aarch64/Lregs.c aarch64/Lresume.c \ - aarch64/Lstash_frame.c aarch64/Lstep.c aarch64/Ltrace.c \ - aarch64/getcontext.S - -libunwind_aarch64_la_SOURCES_aarch64 = $(libunwind_la_SOURCES_aarch64_common) \ - $(libunwind_la_SOURCES_generic) \ - aarch64/Gapply_reg_state.c aarch64/Greg_states_iterate.c \ - aarch64/Gcreate_addr_space.c aarch64/Gget_proc_info.c \ - aarch64/Gget_save_loc.c aarch64/Gglobal.c aarch64/Ginit.c \ - aarch64/Ginit_local.c aarch64/Ginit_remote.c \ - aarch64/Gis_signal_frame.c aarch64/Gregs.c aarch64/Gresume.c \ - aarch64/Gstash_frame.c aarch64/Gstep.c aarch64/Gtrace.c - -# The list of files that go into libunwind and libunwind-arm: -noinst_HEADERS += arm/init.h arm/offsets.h arm/unwind_i.h -libunwind_la_SOURCES_arm_common = $(libunwind_la_SOURCES_common) \ - arm/is_fpreg.c arm/regname.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common) \ - $(libunwind_la_SOURCES_arm_os_local) \ - $(libunwind_la_SOURCES_local) \ - arm/getcontext.S \ - arm/Lapply_reg_state.c arm/Lreg_states_iterate.c \ - arm/Lcreate_addr_space.c arm/Lget_proc_info.c arm/Lget_save_loc.c \ - arm/Lglobal.c arm/Linit.c arm/Linit_local.c arm/Linit_remote.c \ - arm/Lregs.c arm/Lresume.c arm/Lstep.c \ - arm/Lex_tables.c arm/Lstash_frame.c arm/Ltrace.c - -# The list of files that go into libunwind-arm: -libunwind_arm_la_SOURCES_arm = $(libunwind_la_SOURCES_arm_common) \ - $(libunwind_la_SOURCES_arm_os) \ - $(libunwind_la_SOURCES_generic) \ - arm/Gapply_reg_state.c arm/Greg_states_iterate.c \ - arm/Gcreate_addr_space.c arm/Gget_proc_info.c arm/Gget_save_loc.c \ - arm/Gglobal.c arm/Ginit.c arm/Ginit_local.c arm/Ginit_remote.c \ - arm/Gregs.c arm/Gresume.c arm/Gstep.c \ - arm/Gex_tables.c arm/Gstash_frame.c arm/Gtrace.c - -# The list of files that go both into libunwind and libunwind-ia64: -noinst_HEADERS += ia64/init.h ia64/offsets.h ia64/regs.h \ - ia64/ucontext_i.h ia64/unwind_decoder.h ia64/unwind_i.h -libunwind_la_SOURCES_ia64_common = $(libunwind_la_SOURCES_common) \ - ia64/regname.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_ia64 = $(libunwind_la_SOURCES_ia64_common) \ - $(libunwind_la_SOURCES_local) \ - \ - ia64/dyn_info_list.S ia64/getcontext.S \ - \ - ia64/Lapply_reg_state.c ia64/Lreg_states_iterate.c \ - ia64/Lcreate_addr_space.c ia64/Lget_proc_info.c ia64/Lget_save_loc.c \ - ia64/Lglobal.c ia64/Linit.c ia64/Linit_local.c ia64/Linit_remote.c \ - ia64/Linstall_cursor.S ia64/Lis_signal_frame.c ia64/Lparser.c \ - ia64/Lrbs.c ia64/Lregs.c ia64/Lresume.c ia64/Lscript.c ia64/Lstep.c \ - ia64/Ltables.c ia64/Lfind_unwind_table.c - -# The list of files that go into libunwind-ia64: -libunwind_ia64_la_SOURCES_ia64 = $(libunwind_la_SOURCES_ia64_common) \ - $(libunwind_la_SOURCES_generic) \ - ia64/Gapply_reg_state.c ia64/Greg_states_iterate.c \ - ia64/Gcreate_addr_space.c ia64/Gget_proc_info.c ia64/Gget_save_loc.c \ - ia64/Gglobal.c ia64/Ginit.c ia64/Ginit_local.c ia64/Ginit_remote.c \ - ia64/Ginstall_cursor.S ia64/Gis_signal_frame.c ia64/Gparser.c \ - ia64/Grbs.c ia64/Gregs.c ia64/Gresume.c ia64/Gscript.c ia64/Gstep.c \ - ia64/Gtables.c ia64/Gfind_unwind_table.c - -# The list of files that go both into libunwind and libunwind-hppa: -noinst_HEADERS += hppa/init.h hppa/offsets.h hppa/unwind_i.h -libunwind_la_SOURCES_hppa_common = $(libunwind_la_SOURCES_common) \ - hppa/regname.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common) \ - $(libunwind_la_SOURCES_local) \ - hppa/getcontext.S hppa/setcontext.S \ - hppa/Lapply_reg_state.c hppa/Lreg_states_iterate.c \ - hppa/Lcreate_addr_space.c hppa/Lget_save_loc.c hppa/Lglobal.c \ - hppa/Linit.c hppa/Linit_local.c hppa/Linit_remote.c \ - hppa/Lis_signal_frame.c hppa/Lget_proc_info.c hppa/Lregs.c \ - hppa/Lresume.c hppa/Lstep.c - -# The list of files that go into libunwind-hppa: -libunwind_hppa_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common) \ - $(libunwind_la_SOURCES_generic) \ - hppa/Gapply_reg_state.c hppa/Greg_states_iterate.c \ - hppa/Gcreate_addr_space.c hppa/Gget_save_loc.c hppa/Gglobal.c \ - hppa/Ginit.c hppa/Ginit_local.c hppa/Ginit_remote.c \ - hppa/Gis_signal_frame.c hppa/Gget_proc_info.c hppa/Gregs.c \ - hppa/Gresume.c hppa/Gstep.c - -# The list of files that go info libunwind and libunwind-mips: -noinst_HEADERS += mips/init.h mips/offsets.h mips/unwind_i.h -libunwind_la_SOURCES_mips_common = $(libunwind_la_SOURCES_common) \ - mips/is_fpreg.c mips/regname.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_mips = $(libunwind_la_SOURCES_mips_common) \ - $(libunwind_la_SOURCES_local) \ - mips/getcontext.S \ - mips/Lapply_reg_state.c mips/Lreg_states_iterate.c \ - mips/Lcreate_addr_space.c mips/Lget_proc_info.c mips/Lget_save_loc.c \ - mips/Lglobal.c mips/Linit.c mips/Linit_local.c mips/Linit_remote.c \ - mips/Lis_signal_frame.c mips/Lregs.c mips/Lresume.c mips/Lstep.c - -libunwind_mips_la_SOURCES_mips = $(libunwind_la_SOURCES_mips_common) \ - $(libunwind_la_SOURCES_generic) \ - mips/Gapply_reg_state.c mips/Greg_states_iterate.c \ - mips/Gcreate_addr_space.c mips/Gget_proc_info.c mips/Gget_save_loc.c \ - mips/Gglobal.c mips/Ginit.c mips/Ginit_local.c mips/Ginit_remote.c \ - mips/Gis_signal_frame.c mips/Gregs.c mips/Gresume.c mips/Gstep.c - -# The list of files that go info libunwind and libunwind-tilegx: -noinst_HEADERS += tilegx/init.h tilegx/offsets.h tilegx/unwind_i.h -libunwind_la_SOURCES_tilegx_common = $(libunwind_la_SOURCES_common) \ - tilegx/is_fpreg.c tilegx/regname.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_tilegx = $(libunwind_la_SOURCES_tilegx_common) \ - $(libunwind_la_SOURCES_local) \ - tilegx/getcontext.S \ - tilegx/Lapply_reg_state.c tilegx/Lreg_states_iterate.c \ - tilegx/Lcreate_addr_space.c tilegx/Lget_proc_info.c tilegx/Lget_save_loc.c \ - tilegx/Lglobal.c tilegx/Linit.c tilegx/Linit_local.c tilegx/Linit_remote.c \ - tilegx/Lis_signal_frame.c tilegx/Lregs.c tilegx/Lresume.c tilegx/Lstep.c - -libunwind_tilegx_la_SOURCES_tilegx = $(libunwind_la_SOURCES_tilegx_common) \ - $(libunwind_la_SOURCES_generic) \ - tilegx/Gapply_reg_state.c tilegx/Greg_states_iterate.c \ - tilegx/Gcreate_addr_space.c tilegx/Gget_proc_info.c tilegx/Gget_save_loc.c \ - tilegx/Gglobal.c tilegx/Ginit.c tilegx/Ginit_local.c tilegx/Ginit_remote.c \ - tilegx/Gis_signal_frame.c tilegx/Gregs.c tilegx/Gresume.c tilegx/Gstep.c - - -# The list of files that go both into libunwind and libunwind-x86: -noinst_HEADERS += x86/init.h x86/offsets.h x86/unwind_i.h -libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common) \ - x86/is_fpreg.c x86/regname.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ - $(libunwind_la_SOURCES_x86_os_local) \ - $(libunwind_la_SOURCES_local) \ - x86/Lapply_reg_state.c x86/Lreg_states_iterate.c \ - x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c \ - x86/Linit.c x86/Linit_local.c x86/Linit_remote.c \ - x86/Lget_proc_info.c x86/Lregs.c \ - x86/Lresume.c x86/Lstep.c - -# The list of files that go into libunwind-x86: -libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ - $(libunwind_la_SOURCES_x86_os) \ - $(libunwind_la_SOURCES_generic) \ - x86/Gapply_reg_state.c x86/Greg_states_iterate.c \ - x86/Gcreate_addr_space.c x86/Gget_save_loc.c x86/Gglobal.c \ - x86/Ginit.c x86/Ginit_local.c x86/Ginit_remote.c \ - x86/Gget_proc_info.c x86/Gregs.c \ - x86/Gresume.c x86/Gstep.c - -# The list of files that go both into libunwind and libunwind-x86_64: -noinst_HEADERS += x86_64/offsets.h \ - x86_64/init.h x86_64/unwind_i.h x86_64/ucontext_i.h -libunwind_la_SOURCES_x86_64_common = $(libunwind_la_SOURCES_common) \ - x86_64/is_fpreg.c x86_64/regname.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \ - $(libunwind_la_SOURCES_x86_64_os_local) \ - $(libunwind_la_SOURCES_local) \ - x86_64/setcontext.S \ - x86_64/Lapply_reg_state.c x86_64/Lreg_states_iterate.c \ - x86_64/Lcreate_addr_space.c x86_64/Lget_save_loc.c x86_64/Lglobal.c \ - x86_64/Linit.c x86_64/Linit_local.c x86_64/Linit_remote.c \ - x86_64/Lget_proc_info.c x86_64/Lregs.c x86_64/Lresume.c \ - x86_64/Lstash_frame.c x86_64/Lstep.c x86_64/Ltrace.c x86_64/getcontext.S - -# The list of files that go into libunwind-x86_64: -libunwind_x86_64_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \ - $(libunwind_la_SOURCES_x86_64_os) \ - $(libunwind_la_SOURCES_generic) \ - x86_64/Gapply_reg_state.c x86_64/Greg_states_iterate.c \ - x86_64/Gcreate_addr_space.c x86_64/Gget_save_loc.c x86_64/Gglobal.c \ - x86_64/Ginit.c x86_64/Ginit_local.c x86_64/Ginit_remote.c \ - x86_64/Gget_proc_info.c x86_64/Gregs.c x86_64/Gresume.c \ - x86_64/Gstash_frame.c x86_64/Gstep.c x86_64/Gtrace.c - -# The list of local files that go to Power 64 and 32: -libunwind_la_SOURCES_ppc = \ - ppc/Lget_proc_info.c ppc/Lget_save_loc.c ppc/Linit_local.c \ - ppc/Linit_remote.c ppc/Lis_signal_frame.c - -# The list of generic files that go to Power 64 and 32: -libunwind_ppc_la_SOURCES_ppc_generic = \ - ppc/Gget_proc_info.c ppc/Gget_save_loc.c ppc/Ginit_local.c \ - ppc/Ginit_remote.c ppc/Gis_signal_frame.c - -# The list of files that go both into libunwind and libunwind-ppc32: -noinst_HEADERS += ppc32/init.h ppc32/unwind_i.h ppc32/ucontext_i.h -libunwind_la_SOURCES_ppc32_common = $(libunwind_la_SOURCES_common) \ - ppc32/is_fpreg.c ppc32/regname.c ppc32/get_func_addr.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_ppc32 = $(libunwind_la_SOURCES_ppc32_common) \ - $(libunwind_la_SOURCES_local) \ - $(libunwind_la_SOURCES_ppc) \ - ppc32/Lapply_reg_state.c ppc32/Lreg_states_iterate.c \ - ppc32/Lcreate_addr_space.c \ - ppc32/Lglobal.c ppc32/Linit.c \ - ppc32/Lregs.c ppc32/Lresume.c ppc32/Lstep.c - -# The list of files that go into libunwind-ppc32: -libunwind_ppc32_la_SOURCES_ppc32 = $(libunwind_la_SOURCES_ppc32_common) \ - $(libunwind_la_SOURCES_generic) \ - $(libunwind_ppc_la_SOURCES_ppc_generic) \ - ppc32/Gapply_reg_state.c ppc32/Greg_states_iterate.c \ - ppc32/Gcreate_addr_space.c \ - ppc32/Gglobal.c ppc32/Ginit.c \ - ppc32/Gregs.c ppc32/Gresume.c ppc32/Gstep.c - -# The list of files that go both into libunwind and libunwind-ppc64: -noinst_HEADERS += ppc64/init.h ppc64/unwind_i.h ppc64/ucontext_i.h -libunwind_la_SOURCES_ppc64_common = $(libunwind_la_SOURCES_common) \ - ppc64/is_fpreg.c ppc64/regname.c ppc64/get_func_addr.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common) \ - $(libunwind_la_SOURCES_local) \ - $(libunwind_la_SOURCES_ppc) \ - ppc64/Lapply_reg_state.c ppc64/Lreg_states_iterate.c \ - ppc64/Lcreate_addr_space.c \ - ppc64/Lglobal.c ppc64/Linit.c \ - ppc64/Lregs.c ppc64/Lresume.c ppc64/Lstep.c - -# The list of files that go into libunwind-ppc64: -libunwind_ppc64_la_SOURCES_ppc64 = $(libunwind_la_SOURCES_ppc64_common) \ - $(libunwind_la_SOURCES_generic) \ - $(libunwind_ppc_la_SOURCES_ppc_generic) \ - ppc64/Gapply_reg_state.c ppc64/Greg_states_iterate.c \ - ppc64/Gcreate_addr_space.c \ - ppc64/Gglobal.c ppc64/Ginit.c \ - ppc64/Gregs.c ppc64/Gresume.c ppc64/Gstep.c - -# The list of files that go into libunwind and libunwind-sh: -noinst_HEADERS += sh/init.h sh/offsets.h sh/unwind_i.h -libunwind_la_SOURCES_sh_common = $(libunwind_la_SOURCES_common) \ - sh/is_fpreg.c sh/regname.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_sh = $(libunwind_la_SOURCES_sh_common) \ - $(libunwind_la_SOURCES_local) \ - sh/Lapply_reg_state.c sh/Lreg_states_iterate.c \ - sh/Lcreate_addr_space.c sh/Lget_proc_info.c sh/Lget_save_loc.c \ - sh/Lglobal.c sh/Linit.c sh/Linit_local.c sh/Linit_remote.c \ - sh/Lis_signal_frame.c sh/Lregs.c sh/Lresume.c sh/Lstep.c - -libunwind_sh_la_SOURCES_sh = $(libunwind_la_SOURCES_sh_common) \ - $(libunwind_la_SOURCES_generic) \ - sh/Gapply_reg_state.c sh/Greg_states_iterate.c \ - sh/Gcreate_addr_space.c sh/Gget_proc_info.c sh/Gget_save_loc.c \ - sh/Gglobal.c sh/Ginit.c sh/Ginit_local.c sh/Ginit_remote.c \ - sh/Gis_signal_frame.c sh/Gregs.c sh/Gresume.c sh/Gstep.c - -if REMOTE_ONLY -install-exec-hook: -# Nothing to do here.... -else -# -# This is not ideal, but I know of no other way to install an -# alias for a library. For the shared version, we have to do -# a file check before creating the link, because it isn't going -# to be there if the user configured with --disable-shared. -# -install-exec-hook: - if test -f $(DESTDIR)$(libdir)/libunwind-$(arch).a; then \ - cd $(DESTDIR)$(libdir) && $(LN_S) -f libunwind-$(arch).a libunwind-generic.a; \ - fi - if test -f $(DESTDIR)$(libdir)/libunwind-$(arch).so; then \ - cd $(DESTDIR)$(libdir) && $(LN_S) -f libunwind-$(arch).so \ - libunwind-generic.so; \ - fi -endif - -if OS_LINUX - libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_linux) - libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_linux_local) - libunwind_la_SOURCES_x86_os = x86/Gos-linux.c - libunwind_x86_la_SOURCES_os = x86/getcontext-linux.S - libunwind_la_SOURCES_x86_os_local = x86/Los-linux.c - libunwind_la_SOURCES_x86_64_os = x86_64/Gos-linux.c - libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-linux.c - libunwind_la_SOURCES_arm_os = arm/Gos-linux.c - libunwind_coredump_la_SOURCES += coredump/_UCD_access_reg_linux.c -endif - -if OS_HPUX - libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_hpux) - libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_hpux_local) -endif - -if OS_FREEBSD - libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_freebsd) - libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_freebsd_local) - libunwind_la_SOURCES_x86_os = x86/Gos-freebsd.c - libunwind_x86_la_SOURCES_os = x86/getcontext-freebsd.S - libunwind_la_SOURCES_x86_os_local = x86/Los-freebsd.c - libunwind_la_SOURCES_x86_64_os = x86_64/Gos-freebsd.c - libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-freebsd.c - libunwind_la_SOURCES_arm_os = arm/Gos-freebsd.c - libunwind_la_SOURCES_arm_os_local = arm/Los-freebsd.c - libunwind_coredump_la_SOURCES += coredump/_UCD_access_reg_freebsd.c -endif - -if OS_QNX - libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_qnx) - libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_qnx_local) - libunwind_la_SOURCES_arm_os = arm/Gos-other.c - libunwind_la_SOURCES_arm_os_local = arm/Los-other.c -endif - -if ARCH_AARCH64 - lib_LTLIBRARIES += libunwind-aarch64.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_aarch64) - libunwind_aarch64_la_SOURCES = $(libunwind_aarch64_la_SOURCES_aarch64) - libunwind_aarch64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_aarch64_la_LIBADD = libunwind-dwarf-generic.la - libunwind_aarch64_la_LIBADD += libunwind-elf64.la -if !REMOTE_ONLY - libunwind_aarch64_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += aarch64/siglongjmp.S -else -if ARCH_ARM - lib_LTLIBRARIES += libunwind-arm.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_arm) - libunwind_arm_la_SOURCES = $(libunwind_arm_la_SOURCES_arm) - libunwind_arm_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_arm_la_LIBADD = libunwind-dwarf-generic.la - libunwind_arm_la_LIBADD += libunwind-elf32.la -if !REMOTE_ONLY - libunwind_arm_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += arm/siglongjmp.S -else -if ARCH_IA64 - BUILT_SOURCES = Gcursor_i.h Lcursor_i.h -mk_Gcursor_i.s: $(srcdir)/ia64/mk_Gcursor_i.c - $(COMPILE) -S "$(srcdir)/ia64/mk_Gcursor_i.c" -o mk_Gcursor_i.s -mk_Lcursor_i.s: $(srcdir)/ia64/mk_Lcursor_i.c - $(COMPILE) -S "$(srcdir)/ia64/mk_Lcursor_i.c" -o mk_Lcursor_i.s -Gcursor_i.h: mk_Gcursor_i.s - "$(srcdir)/ia64/mk_cursor_i" mk_Gcursor_i.s > Gcursor_i.h -Lcursor_i.h: mk_Lcursor_i.s - "$(srcdir)/ia64/mk_cursor_i" mk_Lcursor_i.s > Lcursor_i.h - - lib_LTLIBRARIES += libunwind-ia64.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_ia64) - libunwind_ia64_la_SOURCES = $(libunwind_ia64_la_SOURCES_ia64) - libunwind_ia64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_ia64_la_LIBADD = libunwind-elf64.la -if !REMOTE_ONLY - libunwind_ia64_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += ia64/setjmp.S ia64/sigsetjmp.S \ - ia64/longjmp.S ia64/siglongjmp.S -else -if ARCH_HPPA - lib_LTLIBRARIES += libunwind-hppa.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_hppa) - libunwind_hppa_la_SOURCES = $(libunwind_hppa_la_SOURCES_hppa) - libunwind_hppa_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_hppa_la_LIBADD = libunwind-dwarf-generic.la - libunwind_hppa_la_LIBADD += libunwind-elf32.la -if !REMOTE_ONLY - libunwind_hppa_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += hppa/siglongjmp.S -else -if ARCH_MIPS - lib_LTLIBRARIES += libunwind-mips.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_mips) - libunwind_mips_la_SOURCES = $(libunwind_mips_la_SOURCES_mips) - libunwind_mips_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_mips_la_LIBADD = libunwind-dwarf-generic.la - libunwind_mips_la_LIBADD += libunwind-elfxx.la -if !REMOTE_ONLY - libunwind_mips_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += mips/siglongjmp.S -else -if ARCH_TILEGX - lib_LTLIBRARIES += libunwind-tilegx.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_tilegx) - libunwind_tilegx_la_SOURCES = $(libunwind_tilegx_la_SOURCES_tilegx) - libunwind_tilegx_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_tilegx_la_LIBADD = libunwind-dwarf-generic.la - libunwind_tilegx_la_LIBADD += libunwind-elfxx.la -if !REMOTE_ONLY - libunwind_tilegx_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += tilegx/siglongjmp.S -else -if ARCH_X86 - lib_LTLIBRARIES += libunwind-x86.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86) $(libunwind_x86_la_SOURCES_os) - libunwind_x86_la_SOURCES = $(libunwind_x86_la_SOURCES_x86) - libunwind_x86_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_x86_la_LIBADD = libunwind-dwarf-generic.la - libunwind_x86_la_LIBADD += libunwind-elf32.la -if !REMOTE_ONLY - libunwind_x86_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += x86/longjmp.S x86/siglongjmp.S -else -if ARCH_X86_64 - lib_LTLIBRARIES += libunwind-x86_64.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86_64) - libunwind_x86_64_la_SOURCES = $(libunwind_x86_64_la_SOURCES_x86_64) - libunwind_x86_64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_x86_64_la_LIBADD = libunwind-dwarf-generic.la - libunwind_x86_64_la_LIBADD += libunwind-elf64.la -if !REMOTE_ONLY - libunwind_x86_64_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += x86_64/longjmp.S x86_64/siglongjmp.S -else -if ARCH_PPC32 - lib_LTLIBRARIES += libunwind-ppc32.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_ppc32) - libunwind_ppc32_la_SOURCES = $(libunwind_ppc32_la_SOURCES_ppc32) - libunwind_ppc32_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_ppc32_la_LIBADD = libunwind-dwarf-generic.la - libunwind_ppc32_la_LIBADD += libunwind-elf32.la -if !REMOTE_ONLY - libunwind_ppc32_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += ppc/longjmp.S ppc/siglongjmp.S -else -if ARCH_PPC64 - lib_LTLIBRARIES += libunwind-ppc64.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_ppc64) - libunwind_ppc64_la_SOURCES = $(libunwind_ppc64_la_SOURCES_ppc64) - libunwind_ppc64_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_ppc64_la_LIBADD = libunwind-dwarf-generic.la - libunwind_ppc64_la_LIBADD += libunwind-elf64.la -if !REMOTE_ONLY - libunwind_ppc64_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += ppc/longjmp.S ppc/siglongjmp.S -else -if ARCH_SH - lib_LTLIBRARIES += libunwind-sh.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_sh) - libunwind_sh_la_SOURCES = $(libunwind_sh_la_SOURCES_sh) - libunwind_sh_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_sh_la_LIBADD = libunwind-dwarf-generic.la - libunwind_sh_la_LIBADD += libunwind-elf32.la -if !REMOTE_ONLY - libunwind_sh_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += sh/siglongjmp.S - -endif # ARCH_SH -endif # ARCH_PPC64 -endif # ARCH_PPC32 -endif # ARCH_X86_64 -endif # ARCH_X86 -endif # ARCH_TILEGX -endif # ARCH_MIPS -endif # ARCH_HPPA -endif # ARCH_IA64 -endif # ARCH_ARM -endif # ARCH_AARCH64 - -# libunwind-setjmp depends on libunwind-$(arch). Therefore must be added -# at the end. -if BUILD_SETJMP -lib_LTLIBRARIES += libunwind-setjmp.la -endif - -# -# Don't link with standard libraries, because those may mention -# libunwind already. -# -libunwind_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -XCClinker -nostdlib \ - $(LDFLAGS_STATIC_LIBCXA) -version-info $(SOVERSION) -libunwind_la_LIBADD += -lc $(LIBCRTS) -libunwind_la_LIBADD += $(LIBLZMA) - -AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/tdep-$(arch) -I. -AM_CCASFLAGS = $(AM_CPPFLAGS) -noinst_HEADERS += unwind/unwind-internal.h - -EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \ - $(libunwind_la_SOURCES_arm) \ - $(libunwind_la_SOURCES_hppa) \ - $(libunwind_la_SOURCES_ia64) \ - $(libunwind_la_SOURCES_mips) \ - $(libunwind_la_SOURCES_sh) \ - $(libunwind_la_SOURCES_x86) \ - $(libunwind_la_SOURCES_os_freebsd) \ - $(libunwind_la_SOURCES_os_linux) \ - $(libunwind_la_SOURCES_os_hpux) \ - $(libunwind_la_SOURCES_os_qnx) \ - $(libunwind_la_SOURCES_common) \ - $(libunwind_la_SOURCES_local) \ - $(libunwind_la_SOURCES_generic) \ - $(libunwind_aarch64_la_SOURCES_aarch64) \ - $(libunwind_arm_la_SOURCES_arm) \ - $(libunwind_hppa_la_SOURCES_hppa) \ - $(libunwind_ia64_la_SOURCES_ia64) \ - $(libunwind_mips_la_SOURCES_mips) \ - $(libunwind_sh_la_SOURCES_sh) \ - $(libunwind_x86_la_SOURCES_x86) \ - $(libunwind_x86_64_la_SOURCES_x86_64) - -MAINTAINERCLEANFILES = Makefile.in - -# The -version-info flag accepts an argument of the form -# `current[:revision[:age]]'. So, passing `-version-info 3:12:1' sets -# current to 3, revision to 12, and age to 1. - -# If either revision or age are omitted, they default to 0. Also note -# that age must be less than or equal to the current interface number. - -# Here are a set of rules to help you update your library version -# information: - -# 1. Start with version information of `0:0:0' for each libtool -# library. - -# 2. Update the version information only immediately before a public -# release of your software. More frequent updates are unnecessary, -# and only guarantee that the current interface number gets larger -# faster. - -# 3. If the library source code has changed at all since the last -# update, then increment revision (`c:r:a' becomes `c:r+1:a'). - -# 4. If any interfaces have been added, removed, or changed since the -# last update, increment current, and set revision to 0. - -# 5. If any interfaces have been added since the last public release, -# then increment age. - -# 6. If any interfaces have been removed since the last public -# release, then set age to 0. diff --git a/contrib/libunwind/src/aarch64/Gapply_reg_state.c b/contrib/libunwind/src/aarch64/Gapply_reg_state.c deleted file mode 100644 index eec93046f56..00000000000 --- a/contrib/libunwind/src/aarch64/Gapply_reg_state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); -} diff --git a/contrib/libunwind/src/aarch64/Gcreate_addr_space.c b/contrib/libunwind/src/aarch64/Gcreate_addr_space.c deleted file mode 100644 index b0f2b0488c9..00000000000 --- a/contrib/libunwind/src/aarch64/Gcreate_addr_space.c +++ /dev/null @@ -1,60 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2012 Tommi Rantala - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "unwind_i.h" - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* AArch64 supports little-endian and big-endian. */ - if (byte_order != 0 && byte_order != __LITTLE_ENDIAN - && byte_order != __BIG_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - /* Default to little-endian for AArch64. */ - if (byte_order == 0 || byte_order == __LITTLE_ENDIAN) - as->big_endian = 0; - else - as->big_endian = 1; - - return as; -#endif -} diff --git a/contrib/libunwind/src/aarch64/Gget_proc_info.c b/contrib/libunwind/src/aarch64/Gget_proc_info.c deleted file mode 100644 index de9199f9958..00000000000 --- a/contrib/libunwind/src/aarch64/Gget_proc_info.c +++ /dev/null @@ -1,39 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - ret = dwarf_make_proc_info (&c->dwarf); - if (ret < 0) - return ret; - - *pi = c->dwarf.pi; - return 0; -} diff --git a/contrib/libunwind/src/aarch64/Gget_save_loc.c b/contrib/libunwind/src/aarch64/Gget_save_loc.c deleted file mode 100644 index 5ccf5cfdb91..00000000000 --- a/contrib/libunwind/src/aarch64/Gget_save_loc.c +++ /dev/null @@ -1,100 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) -{ - struct cursor *c = (struct cursor *) cursor; - dwarf_loc_t loc; - - switch (reg) - { - case UNW_AARCH64_X0: - case UNW_AARCH64_X1: - case UNW_AARCH64_X2: - case UNW_AARCH64_X3: - case UNW_AARCH64_X4: - case UNW_AARCH64_X5: - case UNW_AARCH64_X6: - case UNW_AARCH64_X7: - case UNW_AARCH64_X8: - case UNW_AARCH64_X9: - case UNW_AARCH64_X10: - case UNW_AARCH64_X11: - case UNW_AARCH64_X12: - case UNW_AARCH64_X13: - case UNW_AARCH64_X14: - case UNW_AARCH64_X15: - case UNW_AARCH64_X16: - case UNW_AARCH64_X17: - case UNW_AARCH64_X18: - case UNW_AARCH64_X19: - case UNW_AARCH64_X20: - case UNW_AARCH64_X21: - case UNW_AARCH64_X22: - case UNW_AARCH64_X23: - case UNW_AARCH64_X24: - case UNW_AARCH64_X25: - case UNW_AARCH64_X26: - case UNW_AARCH64_X27: - case UNW_AARCH64_X28: - case UNW_AARCH64_X29: - case UNW_AARCH64_X30: - case UNW_AARCH64_SP: - case UNW_AARCH64_PC: - case UNW_AARCH64_PSTATE: - loc = c->dwarf.loc[reg]; - break; - - default: - loc = DWARF_NULL_LOC; /* default to "not saved" */ - break; - } - - memset (sloc, 0, sizeof (*sloc)); - - if (DWARF_IS_NULL_LOC (loc)) - { - sloc->type = UNW_SLT_NONE; - return 0; - } - -#if !defined(UNW_LOCAL_ONLY) - if (DWARF_IS_REG_LOC (loc)) - { - sloc->type = UNW_SLT_REG; - sloc->u.regnum = DWARF_GET_LOC (loc); - } - else -#endif - { - sloc->type = UNW_SLT_MEMORY; - sloc->u.addr = DWARF_GET_LOC (loc); - } - return 0; -} diff --git a/contrib/libunwind/src/aarch64/Gglobal.c b/contrib/libunwind/src/aarch64/Gglobal.c deleted file mode 100644 index 72e36b2d4d6..00000000000 --- a/contrib/libunwind/src/aarch64/Gglobal.c +++ /dev/null @@ -1,57 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "dwarf_i.h" - -HIDDEN define_lock (aarch64_lock); -HIDDEN int tdep_init_done; - -HIDDEN void -tdep_init (void) -{ - intrmask_t saved_mask; - - sigfillset (&unwi_full_mask); - - lock_acquire (&aarch64_lock, saved_mask); - { - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - mi_init (); - - dwarf_init (); - -#ifndef UNW_REMOTE_ONLY - aarch64_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - } - out: - lock_release (&aarch64_lock, saved_mask); -} diff --git a/contrib/libunwind/src/aarch64/Ginit.c b/contrib/libunwind/src/aarch64/Ginit.c deleted file mode 100644 index ab3999f307c..00000000000 --- a/contrib/libunwind/src/aarch64/Ginit.c +++ /dev/null @@ -1,190 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -PROTECTED unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; - -static inline void * -uc_addr (ucontext_t *uc, int reg) -{ - if (reg >= UNW_AARCH64_X0 && reg < UNW_AARCH64_V0) - return &uc->uc_mcontext.regs[reg]; - else if (reg >= UNW_AARCH64_V0 && reg <= UNW_AARCH64_V31) - return &GET_FPCTX(uc)->vregs[reg - UNW_AARCH64_V0]; - else - return NULL; -} - -# ifdef UNW_LOCAL_ONLY - -HIDDEN void * -tdep_uc_addr (ucontext_t *uc, int reg) -{ - return uc_addr (uc, reg); -} - -# endif /* UNW_LOCAL_ONLY */ - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - -/* XXX fix me: there is currently no way to locate the dyn-info list - by a remote unwinder. On ia64, this is done via a special - unwind-table entry. Perhaps something similar can be done with - DWARF2 unwind info. */ - -static void -put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ - *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - if (write) - { - Debug (16, "mem[%lx] <- %lx\n", addr, *val); - *(unw_word_t *) addr = *val; - } - else - { - *val = *(unw_word_t *) addr; - Debug (16, "mem[%lx] -> %lx\n", addr, *val); - } - return 0; -} - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, - void *arg) -{ - unw_word_t *addr; - ucontext_t *uc = arg; - - if (unw_is_fpreg (reg)) - goto badreg; - - if (!(addr = uc_addr (uc, reg))) - goto badreg; - - if (write) - { - *(unw_word_t *) addr = *val; - Debug (12, "%s <- %lx\n", unw_regname (reg), *val); - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "%s -> %lx\n", unw_regname (reg), *val); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - ucontext_t *uc = arg; - unw_fpreg_t *addr; - - if (!unw_is_fpreg (reg)) - goto badreg; - - if (!(addr = uc_addr (uc, reg))) - goto badreg; - - if (write) - { - Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - *(unw_fpreg_t *) addr = *val; - } - else - { - *val = *(unw_fpreg_t *) addr; - Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - /* attempt to access a non-preserved register */ - return -UNW_EBADREG; -} - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp); -} - -HIDDEN void -aarch64_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; - local_addr_space.acc.find_proc_info = dwarf_find_proc_info; - local_addr_space.acc.put_unwind_info = put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = aarch64_local_resume; - local_addr_space.acc.get_proc_name = get_static_proc_name; - local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); - unw_flush_cache (&local_addr_space, 0, 0); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/aarch64/Ginit_local.c b/contrib/libunwind/src/aarch64/Ginit_local.c deleted file mode 100644 index d284224a369..00000000000 --- a/contrib/libunwind/src/aarch64/Ginit_local.c +++ /dev/null @@ -1,78 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2011-2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "init.h" - -#ifdef UNW_REMOTE_ONLY - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) -{ - return -UNW_EINVAL; -} - -#else /* !UNW_REMOTE_ONLY */ - -static int -unw_init_local_common (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr) -{ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = unw_local_addr_space; - c->dwarf.as_arg = uc; - - return common_init (c, use_prev_instr); -} - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) -{ - return unw_init_local_common(cursor, uc, 1); -} - -PROTECTED int -unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) -{ - if (!flag) - { - return unw_init_local_common(cursor, uc, 1); - } - else if (flag == UNW_INIT_SIGNAL_FRAME) - { - return unw_init_local_common(cursor, uc, 0); - } - else - { - return -UNW_EINVAL; - } -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/aarch64/Ginit_remote.c b/contrib/libunwind/src/aarch64/Ginit_remote.c deleted file mode 100644 index f284e994f4b..00000000000 --- a/contrib/libunwind/src/aarch64/Ginit_remote.c +++ /dev/null @@ -1,45 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "init.h" -#include "unwind_i.h" - -PROTECTED int -unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) -{ -#ifdef UNW_LOCAL_ONLY - return -UNW_EINVAL; -#else /* !UNW_LOCAL_ONLY */ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = as; - c->dwarf.as_arg = as_arg; - return common_init (c, 0); -#endif /* !UNW_LOCAL_ONLY */ -} diff --git a/contrib/libunwind/src/aarch64/Gis_signal_frame.c b/contrib/libunwind/src/aarch64/Gis_signal_frame.c deleted file mode 100644 index 53e32de1313..00000000000 --- a/contrib/libunwind/src/aarch64/Gis_signal_frame.c +++ /dev/null @@ -1,64 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2012 Tommi Rantala - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -/* The restorer stub will always have the form: - - d2801168 movz x8, #0x8b - d4000001 svc #0x0 -*/ - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ -#ifdef __linux__ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - ip = c->dwarf.ip; - - ret = (*a->access_mem) (as, ip, &w0, 0, arg); - if (ret < 0) - return ret; - - /* FIXME: distinguish 32bit insn vs 64bit registers. */ - if (w0 != 0xd4000001d2801168) - return 0; - - return 1; - -#else - return -UNW_ENOINFO; -#endif -} diff --git a/contrib/libunwind/src/aarch64/Greg_states_iterate.c b/contrib/libunwind/src/aarch64/Greg_states_iterate.c deleted file mode 100644 index a39837a1781..00000000000 --- a/contrib/libunwind/src/aarch64/Greg_states_iterate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_reg_states_iterate (&c->dwarf, cb, token); -} diff --git a/contrib/libunwind/src/aarch64/Gregs.c b/contrib/libunwind/src/aarch64/Gregs.c deleted file mode 100644 index a8843734459..00000000000 --- a/contrib/libunwind/src/aarch64/Gregs.c +++ /dev/null @@ -1,118 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - dwarf_loc_t loc = DWARF_NULL_LOC; - unsigned int mask; - - switch (reg) - { - case UNW_AARCH64_X0: - case UNW_AARCH64_X1: - case UNW_AARCH64_X2: - case UNW_AARCH64_X3: - mask = 1 << reg; - if (write) - { - c->dwarf.eh_args[reg] = *valp; - c->dwarf.eh_valid_mask |= mask; - return 0; - } - else if ((c->dwarf.eh_valid_mask & mask) != 0) - { - *valp = c->dwarf.eh_args[reg]; - return 0; - } - else - loc = c->dwarf.loc[reg]; - break; - - case UNW_AARCH64_X30: - if (write) - c->dwarf.ip = *valp; /* update the IP cache */ - case UNW_AARCH64_X4: - case UNW_AARCH64_X5: - case UNW_AARCH64_X6: - case UNW_AARCH64_X7: - case UNW_AARCH64_X8: - case UNW_AARCH64_X9: - case UNW_AARCH64_X10: - case UNW_AARCH64_X11: - case UNW_AARCH64_X12: - case UNW_AARCH64_X13: - case UNW_AARCH64_X14: - case UNW_AARCH64_X15: - case UNW_AARCH64_X16: - case UNW_AARCH64_X17: - case UNW_AARCH64_X18: - case UNW_AARCH64_X19: - case UNW_AARCH64_X20: - case UNW_AARCH64_X21: - case UNW_AARCH64_X22: - case UNW_AARCH64_X23: - case UNW_AARCH64_X24: - case UNW_AARCH64_X25: - case UNW_AARCH64_X26: - case UNW_AARCH64_X27: - case UNW_AARCH64_X28: - case UNW_AARCH64_X29: - case UNW_AARCH64_PC: - case UNW_AARCH64_PSTATE: - loc = c->dwarf.loc[reg]; - break; - - case UNW_AARCH64_SP: - if (write) - return -UNW_EREADONLYREG; - *valp = c->dwarf.cfa; - return 0; - - default: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; - } - - if (write) - return dwarf_put (&c->dwarf, loc, *valp); - else - return dwarf_get (&c->dwarf, loc, valp); -} - -HIDDEN int -tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, - int write) -{ - dwarf_loc_t loc = c->dwarf.loc[reg]; - if (write) - return dwarf_putfp (&c->dwarf, loc, *valp); - else - return dwarf_getfp (&c->dwarf, loc, valp); -} diff --git a/contrib/libunwind/src/aarch64/Gresume.c b/contrib/libunwind/src/aarch64/Gresume.c deleted file mode 100644 index 65517a252d1..00000000000 --- a/contrib/libunwind/src/aarch64/Gresume.c +++ /dev/null @@ -1,198 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2011-2013 Linaro Limited - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" - -#ifndef UNW_REMOTE_ONLY - -HIDDEN inline int -aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ -#ifdef __linux__ - struct cursor *c = (struct cursor *) cursor; - unw_tdep_context_t *uc = c->dwarf.as_arg; - - if (c->sigcontext_format == AARCH64_SCF_NONE) - { - /* Since there are no signals involved here we restore EH and non scratch - registers only. */ - unsigned long regs[24]; - regs[0] = uc->uc_mcontext.regs[0]; - regs[1] = uc->uc_mcontext.regs[1]; - regs[2] = uc->uc_mcontext.regs[2]; - regs[3] = uc->uc_mcontext.regs[3]; - regs[4] = uc->uc_mcontext.regs[19]; - regs[5] = uc->uc_mcontext.regs[20]; - regs[6] = uc->uc_mcontext.regs[21]; - regs[7] = uc->uc_mcontext.regs[22]; - regs[8] = uc->uc_mcontext.regs[23]; - regs[9] = uc->uc_mcontext.regs[24]; - regs[10] = uc->uc_mcontext.regs[25]; - regs[11] = uc->uc_mcontext.regs[26]; - regs[12] = uc->uc_mcontext.regs[27]; - regs[13] = uc->uc_mcontext.regs[28]; - regs[14] = uc->uc_mcontext.regs[29]; /* FP */ - regs[15] = uc->uc_mcontext.regs[30]; /* LR */ - regs[16] = GET_FPCTX(uc)->vregs[8]; - regs[17] = GET_FPCTX(uc)->vregs[9]; - regs[18] = GET_FPCTX(uc)->vregs[10]; - regs[19] = GET_FPCTX(uc)->vregs[11]; - regs[20] = GET_FPCTX(uc)->vregs[12]; - regs[21] = GET_FPCTX(uc)->vregs[13]; - regs[22] = GET_FPCTX(uc)->vregs[14]; - regs[23] = GET_FPCTX(uc)->vregs[15]; - unsigned long sp = uc->uc_mcontext.sp; - - struct regs_overlay { - char x[sizeof(regs)]; - }; - - asm volatile ( - "mov x4, %0\n" - "mov x5, %1\n" - "ldp x0, x1, [x4]\n" - "ldp x2, x3, [x4,16]\n" - "ldp x19, x20, [x4,32]\n" - "ldp x21, x22, [x4,48]\n" - "ldp x23, x24, [x4,64]\n" - "ldp x25, x26, [x4,80]\n" - "ldp x27, x28, [x4,96]\n" - "ldp x29, x30, [x4,112]\n" - "ldp d8, d9, [x4,128]\n" - "ldp d10, d11, [x4,144]\n" - "ldp d12, d13, [x4,160]\n" - "ldp d14, d15, [x4,176]\n" - "mov sp, x5\n" - "ret \n" - : - : "r" (regs), - "r" (sp), - "m" (*(struct regs_overlay *)regs) - ); - } - else - { - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - - if (c->dwarf.eh_valid_mask & 0x1) sc->regs[0] = c->dwarf.eh_args[0]; - if (c->dwarf.eh_valid_mask & 0x2) sc->regs[1] = c->dwarf.eh_args[1]; - if (c->dwarf.eh_valid_mask & 0x4) sc->regs[2] = c->dwarf.eh_args[2]; - if (c->dwarf.eh_valid_mask & 0x8) sc->regs[3] = c->dwarf.eh_args[3]; - - sc->regs[4] = uc->uc_mcontext.regs[4]; - sc->regs[5] = uc->uc_mcontext.regs[5]; - sc->regs[6] = uc->uc_mcontext.regs[6]; - sc->regs[7] = uc->uc_mcontext.regs[7]; - sc->regs[8] = uc->uc_mcontext.regs[8]; - sc->regs[9] = uc->uc_mcontext.regs[9]; - sc->regs[10] = uc->uc_mcontext.regs[10]; - sc->regs[11] = uc->uc_mcontext.regs[11]; - sc->regs[12] = uc->uc_mcontext.regs[12]; - sc->regs[13] = uc->uc_mcontext.regs[13]; - sc->regs[14] = uc->uc_mcontext.regs[14]; - sc->regs[15] = uc->uc_mcontext.regs[15]; - sc->regs[16] = uc->uc_mcontext.regs[16]; - sc->regs[17] = uc->uc_mcontext.regs[17]; - sc->regs[18] = uc->uc_mcontext.regs[18]; - sc->regs[19] = uc->uc_mcontext.regs[19]; - sc->regs[20] = uc->uc_mcontext.regs[20]; - sc->regs[21] = uc->uc_mcontext.regs[21]; - sc->regs[22] = uc->uc_mcontext.regs[22]; - sc->regs[23] = uc->uc_mcontext.regs[23]; - sc->regs[24] = uc->uc_mcontext.regs[24]; - sc->regs[25] = uc->uc_mcontext.regs[25]; - sc->regs[26] = uc->uc_mcontext.regs[26]; - sc->regs[27] = uc->uc_mcontext.regs[27]; - sc->regs[28] = uc->uc_mcontext.regs[28]; - sc->regs[29] = uc->uc_mcontext.regs[29]; - sc->regs[30] = uc->uc_mcontext.regs[30]; - sc->sp = uc->uc_mcontext.sp; - sc->pc = uc->uc_mcontext.pc; - sc->pstate = uc->uc_mcontext.pstate; - - asm volatile ( - "mov sp, %0\n" - "ret %1\n" - : : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc) - ); - } - unreachable(); -#else - printf ("%s: implement me\n", __FUNCTION__); -#endif - return -UNW_EINVAL; -} - -#endif /* !UNW_REMOTE_ONLY */ - -static inline void -establish_machine_state (struct cursor *c) -{ - unw_addr_space_t as = c->dwarf.as; - void *arg = c->dwarf.as_arg; - unw_fpreg_t fpval; - unw_word_t val; - int reg; - - Debug (8, "copying out cursor state\n"); - - for (reg = 0; reg <= UNW_AARCH64_V31; ++reg) - { - Debug (16, "copying %s %d\n", unw_regname (reg), reg); - if (unw_is_fpreg (reg)) - { - if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) - as->acc.access_fpreg (as, reg, &fpval, 1, arg); - } - else - { - if (tdep_access_reg (c, reg, &val, 0) >= 0) - as->acc.access_reg (as, reg, &val, 1, arg); - } - } -} - -PROTECTED int -unw_resume (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - - Debug (1, "(cursor=%p)\n", c); - - if (!c->dwarf.ip) - { - /* This can happen easily when the frame-chain gets truncated - due to bad or missing unwind-info. */ - Debug (1, "refusing to resume execution at address 0\n"); - return -UNW_EINVAL; - } - - establish_machine_state (c); - - return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, - c->dwarf.as_arg); -} diff --git a/contrib/libunwind/src/aarch64/Gstash_frame.c b/contrib/libunwind/src/aarch64/Gstash_frame.c deleted file mode 100644 index 6689af1a61d..00000000000 --- a/contrib/libunwind/src/aarch64/Gstash_frame.c +++ /dev/null @@ -1,89 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY - Copyright (C) 2014 CERN and Aalto University - Contributed by Filip Nyback - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -HIDDEN void -tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) -{ - struct cursor *c = (struct cursor *) dwarf_to_cursor (d); - unw_tdep_frame_t *f = &c->frame_info; - - Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld" - " ra=0x%lx fp [where=%d val=%ld @0x%lx] lr [where=%d val=%ld @0x%lx] " - "sp [where=%d val=%ld @0x%lx]\n", - d->ip, d->cfa, f->frame_type, - rs->reg.where[DWARF_CFA_REG_COLUMN], - rs->reg.val[DWARF_CFA_REG_COLUMN], - rs->reg.val[DWARF_CFA_OFF_COLUMN], - DWARF_GET_LOC(d->loc[rs->ret_addr_column]), - rs->reg.where[FP], rs->reg.val[FP], DWARF_GET_LOC(d->loc[FP]), - rs->reg.where[LR], rs->reg.val[LR], DWARF_GET_LOC(d->loc[LR]), - rs->reg.where[SP], rs->reg.val[SP], DWARF_GET_LOC(d->loc[SP])); - - /* A standard frame is defined as: - - CFA is register-relative offset off FP or SP; - - Return address is saved in LR; - - FP is unsaved or saved at CFA+offset, offset != -1; - - LR is unsaved or saved at CFA+offset, offset != -1; - - SP is unsaved or saved at CFA+offset, offset != -1. */ - if (f->frame_type == UNW_AARCH64_FRAME_OTHER - && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG) - && (rs->reg.val[DWARF_CFA_REG_COLUMN] == FP - || rs->reg.val[DWARF_CFA_REG_COLUMN] == SP) - && labs(rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 29) - && rs->ret_addr_column == LR - && (rs->reg.where[FP] == DWARF_WHERE_UNDEF - || rs->reg.where[FP] == DWARF_WHERE_SAME - || (rs->reg.where[FP] == DWARF_WHERE_CFAREL - && labs(rs->reg.val[FP]) < (1 << 29) - && rs->reg.val[FP]+1 != 0)) - && (rs->reg.where[LR] == DWARF_WHERE_UNDEF - || rs->reg.where[LR] == DWARF_WHERE_SAME - || (rs->reg.where[LR] == DWARF_WHERE_CFAREL - && labs(rs->reg.val[LR]) < (1 << 29) - && rs->reg.val[LR]+1 != 0)) - && (rs->reg.where[SP] == DWARF_WHERE_UNDEF - || rs->reg.where[SP] == DWARF_WHERE_SAME - || (rs->reg.where[SP] == DWARF_WHERE_CFAREL - && labs(rs->reg.val[SP]) < (1 << 29) - && rs->reg.val[SP]+1 != 0))) - { - /* Save information for a standard frame. */ - f->frame_type = UNW_AARCH64_FRAME_STANDARD; - f->cfa_reg_sp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == SP); - f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN]; - if (rs->reg.where[FP] == DWARF_WHERE_CFAREL) - f->fp_cfa_offset = rs->reg.val[FP]; - if (rs->reg.where[LR] == DWARF_WHERE_CFAREL) - f->lr_cfa_offset = rs->reg.val[LR]; - if (rs->reg.where[SP] == DWARF_WHERE_CFAREL) - f->sp_cfa_offset = rs->reg.val[SP]; - Debug (4, " standard frame\n"); - } - else - Debug (4, " unusual frame\n"); -} diff --git a/contrib/libunwind/src/aarch64/Gstep.c b/contrib/libunwind/src/aarch64/Gstep.c deleted file mode 100644 index e38ff9794f5..00000000000 --- a/contrib/libunwind/src/aarch64/Gstep.c +++ /dev/null @@ -1,189 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2011-2013 Linaro Limited - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" - -/* Recognise PLT entries such as: - 40ddf0: b0000570 adrp x16, 4ba000 <_GLOBAL_OFFSET_TABLE_+0x2a8> - 40ddf4: f9433611 ldr x17, [x16,#1640] - 40ddf8: 9119a210 add x16, x16, #0x668 - 40ddfc: d61f0220 br x17 */ -static int -is_plt_entry (struct dwarf_cursor *c) -{ - unw_word_t w0, w1; - unw_accessors_t *a; - int ret; - - a = unw_get_accessors (c->as); - if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0 - || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0) - return 0; - - ret = (((w0 & 0xff0000009f000000) == 0xf900000090000000) - && ((w1 & 0xffffffffff000000) == 0xd61f022091000000)); - - Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret); - return ret; -} - -PROTECTED int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; - struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); - - if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) - return -UNW_EUNSPEC; - - ret = unw_is_signal_frame (cursor); - Debug(1, "unw_is_signal_frame()=%d\n", ret); - - /* Save the SP and PC to be able to return execution at this point - later in time (unw_resume). */ - c->sigcontext_sp = c->dwarf.cfa; - c->sigcontext_pc = c->dwarf.ip; - - if (ret) - { - c->sigcontext_format = AARCH64_SCF_LINUX_RT_SIGFRAME; - sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; - } - else - return -UNW_EUNSPEC; - - c->sigcontext_addr = sc_addr; - c->frame_info.frame_type = UNW_AARCH64_FRAME_SIGRETURN; - c->frame_info.cfa_reg_offset = sc_addr - sp_addr; - - /* Update the dwarf cursor. - Set the location of the registers to the corresponding addresses of the - uc_mcontext / sigcontext structure contents. */ - c->dwarf.loc[UNW_AARCH64_X0] = DWARF_LOC (sc_addr + LINUX_SC_X0_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X1] = DWARF_LOC (sc_addr + LINUX_SC_X1_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X2] = DWARF_LOC (sc_addr + LINUX_SC_X2_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X3] = DWARF_LOC (sc_addr + LINUX_SC_X3_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X4] = DWARF_LOC (sc_addr + LINUX_SC_X4_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X5] = DWARF_LOC (sc_addr + LINUX_SC_X5_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X6] = DWARF_LOC (sc_addr + LINUX_SC_X6_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X7] = DWARF_LOC (sc_addr + LINUX_SC_X7_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X8] = DWARF_LOC (sc_addr + LINUX_SC_X8_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X9] = DWARF_LOC (sc_addr + LINUX_SC_X9_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X10] = DWARF_LOC (sc_addr + LINUX_SC_X10_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X11] = DWARF_LOC (sc_addr + LINUX_SC_X11_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X12] = DWARF_LOC (sc_addr + LINUX_SC_X12_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X13] = DWARF_LOC (sc_addr + LINUX_SC_X13_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X14] = DWARF_LOC (sc_addr + LINUX_SC_X14_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X15] = DWARF_LOC (sc_addr + LINUX_SC_X15_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X16] = DWARF_LOC (sc_addr + LINUX_SC_X16_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X17] = DWARF_LOC (sc_addr + LINUX_SC_X17_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X18] = DWARF_LOC (sc_addr + LINUX_SC_X18_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X19] = DWARF_LOC (sc_addr + LINUX_SC_X19_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X20] = DWARF_LOC (sc_addr + LINUX_SC_X20_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X21] = DWARF_LOC (sc_addr + LINUX_SC_X21_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X22] = DWARF_LOC (sc_addr + LINUX_SC_X22_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X23] = DWARF_LOC (sc_addr + LINUX_SC_X23_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X24] = DWARF_LOC (sc_addr + LINUX_SC_X24_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X25] = DWARF_LOC (sc_addr + LINUX_SC_X25_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X26] = DWARF_LOC (sc_addr + LINUX_SC_X26_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X27] = DWARF_LOC (sc_addr + LINUX_SC_X27_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X28] = DWARF_LOC (sc_addr + LINUX_SC_X28_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X29] = DWARF_LOC (sc_addr + LINUX_SC_X29_OFF, 0); - c->dwarf.loc[UNW_AARCH64_X30] = DWARF_LOC (sc_addr + LINUX_SC_X30_OFF, 0); - c->dwarf.loc[UNW_AARCH64_SP] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0); - c->dwarf.loc[UNW_AARCH64_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); - c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_LOC (sc_addr + LINUX_SC_PSTATE_OFF, 0); - - /* Set SP/CFA and PC/IP. */ - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa); - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip); - - c->dwarf.pi_valid = 0; - c->dwarf.use_prev_instr = 0; - - return 1; -} - -PROTECTED int -unw_step (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx))\n", - c, c->dwarf.ip, c->dwarf.cfa); - - /* Check if this is a signal frame. */ - if (unw_is_signal_frame (cursor) > 0) - return unw_handle_signal_frame (cursor); - - ret = dwarf_step (&c->dwarf); - Debug(1, "dwarf_step()=%d\n", ret); - - if (unlikely (ret == -UNW_ESTOPUNWIND)) - return ret; - - if (unlikely (ret < 0)) - { - /* DWARF failed. */ - if (is_plt_entry (&c->dwarf)) - { - Debug (2, "found plt entry\n"); - c->frame_info.frame_type = UNW_AARCH64_FRAME_STANDARD; - } - else - { - Debug (2, "fallback\n"); - c->frame_info.frame_type = UNW_AARCH64_FRAME_GUESSED; - } - /* Use link register (X30). */ - c->frame_info.cfa_reg_offset = 0; - c->frame_info.cfa_reg_sp = 0; - c->frame_info.fp_cfa_offset = -1; - c->frame_info.lr_cfa_offset = -1; - c->frame_info.sp_cfa_offset = -1; - c->dwarf.loc[UNW_AARCH64_PC] = c->dwarf.loc[UNW_AARCH64_X30]; - c->dwarf.loc[UNW_AARCH64_X30] = DWARF_NULL_LOC; - if (!DWARF_IS_NULL_LOC (c->dwarf.loc[UNW_AARCH64_PC])) - { - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip); - if (ret < 0) - { - Debug (2, "failed to get pc from link register: %d\n", ret); - return ret; - } - Debug (2, "link register (x30) = 0x%016lx\n", c->dwarf.ip); - ret = 1; - } - else - c->dwarf.ip = 0; - } - - return (c->dwarf.ip == 0) ? 0 : 1; -} diff --git a/contrib/libunwind/src/aarch64/Gtrace.c b/contrib/libunwind/src/aarch64/Gtrace.c deleted file mode 100644 index c67faf0e357..00000000000 --- a/contrib/libunwind/src/aarch64/Gtrace.c +++ /dev/null @@ -1,548 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY - Copyright (C) 2014 CERN and Aalto University - Contributed by Filip Nyback - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" -#include -#include - -#pragma weak pthread_once -#pragma weak pthread_key_create -#pragma weak pthread_getspecific -#pragma weak pthread_setspecific - -/* Initial hash table size. Table expands by 2 bits (times four). */ -#define HASH_MIN_BITS 14 - -typedef struct -{ - unw_tdep_frame_t *frames; - size_t log_size; - size_t used; - size_t dtor_count; /* Counts how many times our destructor has already - been called. */ -} unw_trace_cache_t; - -static const unw_tdep_frame_t empty_frame = { 0, UNW_AARCH64_FRAME_OTHER, -1, -1, 0, -1, -1, -1 }; -static define_lock (trace_init_lock); -static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT; -static sig_atomic_t trace_cache_once_happen; -static pthread_key_t trace_cache_key; -static struct mempool trace_cache_pool; -static __thread unw_trace_cache_t *tls_cache; -static __thread int tls_cache_destroyed; - -/* Free memory for a thread's trace cache. */ -static void -trace_cache_free (void *arg) -{ - unw_trace_cache_t *cache = arg; - if (++cache->dtor_count < PTHREAD_DESTRUCTOR_ITERATIONS) - { - /* Not yet our turn to get destroyed. Re-install ourselves into the key. */ - pthread_setspecific(trace_cache_key, cache); - Debug(5, "delayed freeing cache %p (%zx to go)\n", cache, - PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count); - return; - } - tls_cache_destroyed = 1; - tls_cache = NULL; - munmap (cache->frames, (1u << cache->log_size) * sizeof(unw_tdep_frame_t)); - mempool_free (&trace_cache_pool, cache); - Debug(5, "freed cache %p\n", cache); -} - -/* Initialise frame tracing for threaded use. */ -static void -trace_cache_init_once (void) -{ - pthread_key_create (&trace_cache_key, &trace_cache_free); - mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); - trace_cache_once_happen = 1; -} - -static unw_tdep_frame_t * -trace_cache_buckets (size_t n) -{ - unw_tdep_frame_t *frames; - size_t i; - - GET_MEMORY(frames, n * sizeof (unw_tdep_frame_t)); - if (likely(frames != NULL)) - for (i = 0; i < n; ++i) - frames[i] = empty_frame; - - return frames; -} - -/* Allocate and initialise hash table for frame cache lookups. - Returns the cache initialised with (1u << HASH_LOW_BITS) hash - buckets, or NULL if there was a memory allocation problem. */ -static unw_trace_cache_t * -trace_cache_create (void) -{ - unw_trace_cache_t *cache; - - if (tls_cache_destroyed) - { - /* The current thread is in the process of exiting. Don't recreate - cache, as we wouldn't have another chance to free it. */ - Debug(5, "refusing to reallocate cache: " - "thread-locals are being deallocated\n"); - return NULL; - } - - if (! (cache = mempool_alloc(&trace_cache_pool))) - { - Debug(5, "failed to allocate cache\n"); - return NULL; - } - - if (! (cache->frames = trace_cache_buckets(1u << HASH_MIN_BITS))) - { - Debug(5, "failed to allocate buckets\n"); - mempool_free(&trace_cache_pool, cache); - return NULL; - } - - cache->log_size = HASH_MIN_BITS; - cache->used = 0; - cache->dtor_count = 0; - tls_cache_destroyed = 0; /* Paranoia: should already be 0. */ - Debug(5, "allocated cache %p\n", cache); - return cache; -} - -/* Expand the hash table in the frame cache if possible. This always - quadruples the hash size, and clears all previous frame entries. */ -static int -trace_cache_expand (unw_trace_cache_t *cache) -{ - size_t old_size = (1u << cache->log_size); - size_t new_log_size = cache->log_size + 2; - unw_tdep_frame_t *new_frames = trace_cache_buckets (1u << new_log_size); - - if (unlikely(! new_frames)) - { - Debug(5, "failed to expand cache to 2^%lu buckets\n", new_log_size); - return -UNW_ENOMEM; - } - - Debug(5, "expanded cache from 2^%lu to 2^%lu buckets\n", cache->log_size, new_log_size); - munmap(cache->frames, old_size * sizeof(unw_tdep_frame_t)); - cache->frames = new_frames; - cache->log_size = new_log_size; - cache->used = 0; - return 0; -} - -static unw_trace_cache_t * -trace_cache_get_unthreaded (void) -{ - unw_trace_cache_t *cache; - intrmask_t saved_mask; - static unw_trace_cache_t *global_cache = NULL; - lock_acquire (&trace_init_lock, saved_mask); - if (! global_cache) - { - mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); - global_cache = trace_cache_create (); - } - cache = global_cache; - lock_release (&trace_init_lock, saved_mask); - Debug(5, "using cache %p\n", cache); - return cache; -} - -/* Get the frame cache for the current thread. Create it if there is none. */ -static unw_trace_cache_t * -trace_cache_get (void) -{ - unw_trace_cache_t *cache; - if (likely (pthread_once != NULL)) - { - pthread_once(&trace_cache_once, &trace_cache_init_once); - if (!trace_cache_once_happen) - { - return trace_cache_get_unthreaded(); - } - if (! (cache = tls_cache)) - { - cache = trace_cache_create(); - pthread_setspecific(trace_cache_key, cache); - tls_cache = cache; - } - Debug(5, "using cache %p\n", cache); - return cache; - } - else - { - return trace_cache_get_unthreaded(); - } -} - -/* Initialise frame properties for address cache slot F at address - PC using current CFA, FP and SP values. Modifies CURSOR to - that location, performs one unw_step(), and fills F with what - was discovered about the location. Returns F. - - FIXME: This probably should tell DWARF handling to never evaluate - or use registers other than FP, SP and PC in case there is - highly unusual unwind info which uses these creatively. */ -static unw_tdep_frame_t * -trace_init_addr (unw_tdep_frame_t *f, - unw_cursor_t *cursor, - unw_word_t cfa, - unw_word_t pc, - unw_word_t fp, - unw_word_t sp) -{ - struct cursor *c = (struct cursor *) cursor; - struct dwarf_cursor *d = &c->dwarf; - int ret = -UNW_EINVAL; - - /* Initialise frame properties: unknown, not last. */ - f->virtual_address = pc; - f->frame_type = UNW_AARCH64_FRAME_OTHER; - f->last_frame = 0; - f->cfa_reg_sp = -1; - f->cfa_reg_offset = 0; - f->fp_cfa_offset = -1; - f->lr_cfa_offset = -1; - f->sp_cfa_offset = -1; - - /* Reinitialise cursor to this instruction - but undo next/prev PC - adjustment because unw_step will redo it - and force PC, FP and - SP into register locations (=~ ucontext we keep), then set - their desired values. Then perform the step. */ - d->ip = pc + d->use_prev_instr; - d->cfa = cfa; - d->loc[UNW_AARCH64_X29] = DWARF_REG_LOC (d, UNW_AARCH64_X29); - d->loc[UNW_AARCH64_SP] = DWARF_REG_LOC (d, UNW_AARCH64_SP); - d->loc[UNW_AARCH64_PC] = DWARF_REG_LOC (d, UNW_AARCH64_PC); - c->frame_info = *f; - - if (likely(dwarf_put (d, d->loc[UNW_AARCH64_X29], fp) >= 0) - && likely(dwarf_put (d, d->loc[UNW_AARCH64_SP], sp) >= 0) - && likely(dwarf_put (d, d->loc[UNW_AARCH64_PC], pc) >= 0) - && likely((ret = unw_step (cursor)) >= 0)) - *f = c->frame_info; - - /* If unw_step() stopped voluntarily, remember that, even if it - otherwise could not determine anything useful. This avoids - failing trace if we hit frames without unwind info, which is - common for the outermost frame (CRT stuff) on many systems. - This avoids failing trace in very common circumstances; failing - to unw_step() loop wouldn't produce any better result. */ - if (ret == 0) - f->last_frame = -1; - - Debug (3, "frame va %lx type %d last %d cfa %s+%d fp @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n", - f->virtual_address, f->frame_type, f->last_frame, - f->cfa_reg_sp ? "sp" : "fp", f->cfa_reg_offset, - f->fp_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset); - - return f; -} - -/* Look up and if necessary fill in frame attributes for address PC - in CACHE using current CFA, FP and SP values. Uses CURSOR to - perform any unwind steps necessary to fill the cache. Returns the - frame cache slot which describes RIP. */ -static unw_tdep_frame_t * -trace_lookup (unw_cursor_t *cursor, - unw_trace_cache_t *cache, - unw_word_t cfa, - unw_word_t pc, - unw_word_t fp, - unw_word_t sp) -{ - /* First look up for previously cached information using cache as - linear probing hash table with probe step of 1. Majority of - lookups should be completed within few steps, but it is very - important the hash table does not fill up, or performance falls - off the cliff. */ - uint64_t i, addr; - uint64_t cache_size = 1u << cache->log_size; - uint64_t slot = ((pc * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1); - unw_tdep_frame_t *frame; - - for (i = 0; i < 16; ++i) - { - frame = &cache->frames[slot]; - addr = frame->virtual_address; - - /* Return if we found the address. */ - if (likely(addr == pc)) - { - Debug (4, "found address after %ld steps\n", i); - return frame; - } - - /* If slot is empty, reuse it. */ - if (likely(! addr)) - break; - - /* Linear probe to next slot candidate, step = 1. */ - if (++slot >= cache_size) - slot -= cache_size; - } - - /* If we collided after 16 steps, or if the hash is more than half - full, force the hash to expand. Fill the selected slot, whether - it's free or collides. Note that hash expansion drops previous - contents; further lookups will refill the hash. */ - Debug (4, "updating slot %lu after %ld steps, replacing 0x%lx\n", slot, i, addr); - if (unlikely(addr || cache->used >= cache_size / 2)) - { - if (unlikely(trace_cache_expand (cache) < 0)) - return NULL; - - cache_size = 1u << cache->log_size; - slot = ((pc * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1); - frame = &cache->frames[slot]; - addr = frame->virtual_address; - } - - if (! addr) - ++cache->used; - - return trace_init_addr (frame, cursor, cfa, pc, fp, sp); -} - -/* Fast stack backtrace for AArch64. - - This is used by backtrace() implementation to accelerate frequent - queries for current stack, without any desire to unwind. It fills - BUFFER with the call tree from CURSOR upwards for at most SIZE - stack levels. The first frame, backtrace itself, is omitted. When - called, SIZE should give the maximum number of entries that can be - stored into BUFFER. Uses an internal thread-specific cache to - accelerate queries. - - The caller should fall back to a unw_step() loop if this function - fails by returning -UNW_ESTOPUNWIND, meaning the routine hit a - stack frame that is too complex to be traced in the fast path. - - This function is tuned for clients which only need to walk the - stack to get the call tree as fast as possible but without any - other details, for example profilers sampling the stack thousands - to millions of times per second. The routine handles the most - common AArch64 ABI stack layouts: CFA is FP or SP plus/minus - constant offset, return address is in LR, and FP, LR and SP are - either unchanged or saved on stack at constant offset from the CFA; - the signal return frame; and frames without unwind info provided - they are at the outermost (final) frame or can conservatively be - assumed to be frame-pointer based. - - Any other stack layout will cause the routine to give up. There - are only a handful of relatively rarely used functions which do - not have a stack in the standard form: vfork, longjmp, setcontext - and _dl_runtime_profile on common linux systems for example. - - On success BUFFER and *SIZE reflect the trace progress up to *SIZE - stack levels or the outermost frame, which ever is less. It may - stop short of outermost frame if unw_step() loop would also do so, - e.g. if there is no more unwind information; this is not reported - as an error. - - The function returns a negative value for errors, -UNW_ESTOPUNWIND - if tracing stopped because of an unusual frame unwind info. The - BUFFER and *SIZE reflect tracing progress up to the error frame. - - Callers of this function would normally look like this: - - unw_cursor_t cur; - unw_context_t ctx; - void addrs[128]; - int depth = 128; - int ret; - - unw_getcontext(&ctx); - unw_init_local(&cur, &ctx); - if ((ret = unw_tdep_trace(&cur, addrs, &depth)) < 0) - { - depth = 0; - unw_getcontext(&ctx); - unw_init_local(&cur, &ctx); - while ((ret = unw_step(&cur)) > 0 && depth < 128) - { - unw_word_t ip; - unw_get_reg(&cur, UNW_REG_IP, &ip); - addresses[depth++] = (void *) ip; - } - } -*/ -HIDDEN int -tdep_trace (unw_cursor_t *cursor, void **buffer, int *size) -{ - struct cursor *c = (struct cursor *) cursor; - struct dwarf_cursor *d = &c->dwarf; - unw_trace_cache_t *cache; - unw_word_t fp, sp, pc, cfa, lr; - int maxdepth = 0; - int depth = 0; - int ret; - - /* Check input parametres. */ - if (unlikely(! cursor || ! buffer || ! size || (maxdepth = *size) <= 0)) - return -UNW_EINVAL; - - Debug (1, "begin ip 0x%lx cfa 0x%lx\n", d->ip, d->cfa); - - /* Tell core dwarf routines to call back to us. */ - d->stash_frames = 1; - - /* Determine initial register values. These are direct access safe - because we know they come from the initial machine context. */ - pc = d->ip; - sp = cfa = d->cfa; - ACCESS_MEM_FAST(ret, 0, d, DWARF_GET_LOC(d->loc[UNW_AARCH64_X29]), fp); - assert(ret == 0); - lr = 0; - - /* Get frame cache. */ - if (unlikely(! (cache = trace_cache_get()))) - { - Debug (1, "returning %d, cannot get trace cache\n", -UNW_ENOMEM); - *size = 0; - d->stash_frames = 0; - return -UNW_ENOMEM; - } - - /* Trace the stack upwards, starting from current RIP. Adjust - the RIP address for previous/next instruction as the main - unwinding logic would also do. We undo this before calling - back into unw_step(). */ - while (depth < maxdepth) - { - pc -= d->use_prev_instr; - Debug (2, "depth %d cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n", - depth, cfa, pc, sp, fp); - - /* See if we have this address cached. If not, evaluate enough of - the dwarf unwind information to fill the cache line data, or to - decide this frame cannot be handled in fast trace mode. We - cache negative results too to prevent unnecessary dwarf parsing - for common failures. */ - unw_tdep_frame_t *f = trace_lookup (cursor, cache, cfa, pc, fp, sp); - - /* If we don't have information for this frame, give up. */ - if (unlikely(! f)) - { - ret = -UNW_ENOINFO; - break; - } - - Debug (3, "frame va %lx type %d last %d cfa %s+%d fp @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n", - f->virtual_address, f->frame_type, f->last_frame, - f->cfa_reg_sp ? "sp" : "fp", f->cfa_reg_offset, - f->fp_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset); - - assert (f->virtual_address == pc); - - /* Stop if this was the last frame. In particular don't evaluate - new register values as it may not be safe - we don't normally - run with full validation on, and do not want to - and there's - enough bad unwind info floating around that we need to trust - what unw_step() previously said, in potentially bogus frames. */ - if (f->last_frame) - break; - - /* Evaluate CFA and registers for the next frame. */ - switch (f->frame_type) - { - case UNW_AARCH64_FRAME_GUESSED: - /* Fall thru to standard processing after forcing validation. */ - c->validate = 1; - - case UNW_AARCH64_FRAME_STANDARD: - /* Advance standard traceable frame. */ - cfa = (f->cfa_reg_sp ? sp : fp) + f->cfa_reg_offset; - if (likely(f->lr_cfa_offset != -1)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->lr_cfa_offset, pc); - else if (lr != 0) - { - /* Use the saved link register as the new pc. */ - pc = lr; - lr = 0; - } - if (likely(ret >= 0) && likely(f->fp_cfa_offset != -1)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->fp_cfa_offset, fp); - - /* Don't bother reading SP from DWARF, CFA becomes new SP. */ - sp = cfa; - - /* Next frame needs to back up for unwind info lookup. */ - d->use_prev_instr = 1; - break; - - case UNW_AARCH64_FRAME_SIGRETURN: - cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t. */ - - ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_PC_OFF, pc); - if (likely(ret >= 0)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_X29_OFF, fp); - if (likely(ret >= 0)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_SP_OFF, sp); - /* Save the link register here in case we end up in a function that - doesn't save the link register in the prologue, e.g. kill. */ - if (likely(ret >= 0)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_X30_OFF, lr); - - /* Resume stack at signal restoration point. The stack is not - necessarily continuous here, especially with sigaltstack(). */ - cfa = sp; - - /* Next frame should not back up. */ - d->use_prev_instr = 0; - break; - - default: - /* We cannot trace through this frame, give up and tell the - caller we had to stop. Data collected so far may still be - useful to the caller, so let it know how far we got. */ - ret = -UNW_ESTOPUNWIND; - break; - } - - Debug (4, "new cfa 0x%lx pc 0x%lx sp 0x%lx fp 0x%lx\n", - cfa, pc, sp, fp); - - /* If we failed or ended up somewhere bogus, stop. */ - if (unlikely(ret < 0 || pc < 0x4000)) - break; - - /* Record this address in stack trace. We skipped the first address. */ - buffer[depth++] = (void *) (pc - d->use_prev_instr); - } - -#if UNW_DEBUG - Debug (1, "returning %d, depth %d\n", ret, depth); -#endif - *size = depth; - return ret; -} diff --git a/contrib/libunwind/src/aarch64/Lapply_reg_state.c b/contrib/libunwind/src/aarch64/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/aarch64/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Lcreate_addr_space.c b/contrib/libunwind/src/aarch64/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901..00000000000 --- a/contrib/libunwind/src/aarch64/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Lget_proc_info.c b/contrib/libunwind/src/aarch64/Lget_proc_info.c deleted file mode 100644 index 69028b019fc..00000000000 --- a/contrib/libunwind/src/aarch64/Lget_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Lget_save_loc.c b/contrib/libunwind/src/aarch64/Lget_save_loc.c deleted file mode 100644 index 9ea048a9076..00000000000 --- a/contrib/libunwind/src/aarch64/Lget_save_loc.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_save_loc.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Lglobal.c b/contrib/libunwind/src/aarch64/Lglobal.c deleted file mode 100644 index 6d7b489e14b..00000000000 --- a/contrib/libunwind/src/aarch64/Lglobal.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Linit.c b/contrib/libunwind/src/aarch64/Linit.c deleted file mode 100644 index e9abfdd46a3..00000000000 --- a/contrib/libunwind/src/aarch64/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Linit_local.c b/contrib/libunwind/src/aarch64/Linit_local.c deleted file mode 100644 index 68a1687e854..00000000000 --- a/contrib/libunwind/src/aarch64/Linit_local.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_local.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Linit_remote.c b/contrib/libunwind/src/aarch64/Linit_remote.c deleted file mode 100644 index 58cb04ab7cd..00000000000 --- a/contrib/libunwind/src/aarch64/Linit_remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_remote.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Lis_signal_frame.c b/contrib/libunwind/src/aarch64/Lis_signal_frame.c deleted file mode 100644 index b9a7c4f51ad..00000000000 --- a/contrib/libunwind/src/aarch64/Lis_signal_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gis_signal_frame.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Lreg_states_iterate.c b/contrib/libunwind/src/aarch64/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/aarch64/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Lregs.c b/contrib/libunwind/src/aarch64/Lregs.c deleted file mode 100644 index 2c9c75cd7d9..00000000000 --- a/contrib/libunwind/src/aarch64/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Lresume.c b/contrib/libunwind/src/aarch64/Lresume.c deleted file mode 100644 index 41a8cf003de..00000000000 --- a/contrib/libunwind/src/aarch64/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Lstash_frame.c b/contrib/libunwind/src/aarch64/Lstash_frame.c deleted file mode 100644 index 77587803d08..00000000000 --- a/contrib/libunwind/src/aarch64/Lstash_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstash_frame.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Lstep.c b/contrib/libunwind/src/aarch64/Lstep.c deleted file mode 100644 index c1ac3c7547f..00000000000 --- a/contrib/libunwind/src/aarch64/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/contrib/libunwind/src/aarch64/Ltrace.c b/contrib/libunwind/src/aarch64/Ltrace.c deleted file mode 100644 index fcd3f239c9e..00000000000 --- a/contrib/libunwind/src/aarch64/Ltrace.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gtrace.c" -#endif diff --git a/contrib/libunwind/src/aarch64/gen-offsets.c b/contrib/libunwind/src/aarch64/gen-offsets.c deleted file mode 100644 index eadc2377d8f..00000000000 --- a/contrib/libunwind/src/aarch64/gen-offsets.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include -#include -#include - -#define UC(N,X) \ - printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X)) - -#define SC(N,X) \ - printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X)) - -int -main (void) -{ - printf ( -"/* Linux-specific definitions: */\n\n" - -"/* Define various structure offsets to simplify cross-compilation. */\n\n" - -"/* Offsets for AArch64 Linux \"ucontext_t\": */\n\n"); - - UC ("FLAGS", uc_flags); - UC ("LINK", uc_link); - UC ("STACK", uc_stack); - UC ("MCONTEXT", uc_mcontext); - UC ("SIGMASK", uc_sigmask); - - printf ("\n/* Offsets for AArch64 Linux \"struct sigcontext\": */\n\n"); - - SC ("R0", regs[0]); - SC ("R1", regs[1]); - SC ("R2", regs[2]); - SC ("R3", regs[3]); - SC ("R4", regs[4]); - SC ("R5", regs[5]); - SC ("R6", regs[6]); - SC ("R7", regs[7]); - SC ("R8", regs[8]); - SC ("R9", regs[9]); - SC ("R10", regs[10]); - SC ("R11", regs[11]); - SC ("R12", regs[12]); - SC ("R13", regs[13]); - SC ("R14", regs[14]); - SC ("R15", regs[15]); - SC ("R16", regs[16]); - SC ("R17", regs[17]); - SC ("R18", regs[18]); - SC ("R19", regs[19]); - SC ("R20", regs[20]); - SC ("R21", regs[21]); - SC ("R22", regs[22]); - SC ("R23", regs[23]); - SC ("R24", regs[24]); - SC ("R25", regs[25]); - SC ("R26", regs[26]); - SC ("R27", regs[27]); - SC ("R28", regs[28]); - SC ("R29", regs[29]); - SC ("R30", regs[30]); - SC ("R31", regs[31]); - - SC ("PC", pc); - SC ("SP", sp); - SC ("Fault", fault_address); - SC ("state", pstate); - return 0; -} diff --git a/contrib/libunwind/src/aarch64/getcontext.S b/contrib/libunwind/src/aarch64/getcontext.S deleted file mode 100644 index 25ed5b66be7..00000000000 --- a/contrib/libunwind/src/aarch64/getcontext.S +++ /dev/null @@ -1,52 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 Google, Inc - Contributed by Paul Pluzhnikov - Copyright (C) 2010 Konstantin Belousov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "offsets.h" - -/* int _Uaarch64_getcontext_trace (unw_tdep_context_t *ucp) - - Saves limited machine context in UCP necessary for fast trace. If fast trace - fails, caller will have to get the full context. -*/ - - .global _Uaarch64_getcontext_trace - .hidden _Uaarch64_getcontext_trace - .type _Uaarch64_getcontext_trace, @function -_Uaarch64_getcontext_trace: - .cfi_startproc - - /* Save only FP, SP, PC - exclude this call. */ - str x29, [x0, #(LINUX_UC_MCONTEXT_OFF + LINUX_SC_X29_OFF)] - mov x9, sp - str x9, [x0, #(LINUX_UC_MCONTEXT_OFF + LINUX_SC_SP_OFF)] - str x30, [x0, #(LINUX_UC_MCONTEXT_OFF + LINUX_SC_PC_OFF)] - - ret - .cfi_endproc - .size _Uaarch64_getcontext_trace, . - _Uaarch64_getcontext_trace - - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits diff --git a/contrib/libunwind/src/aarch64/init.h b/contrib/libunwind/src/aarch64/init.h deleted file mode 100644 index 5dab60bb64e..00000000000 --- a/contrib/libunwind/src/aarch64/init.h +++ /dev/null @@ -1,126 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2012 Tommi Rantala - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static inline int -common_init (struct cursor *c, unsigned use_prev_instr) -{ - int ret, i; - - c->dwarf.loc[UNW_AARCH64_X0] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X0); - c->dwarf.loc[UNW_AARCH64_X1] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X1); - c->dwarf.loc[UNW_AARCH64_X2] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X2); - c->dwarf.loc[UNW_AARCH64_X3] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X3); - c->dwarf.loc[UNW_AARCH64_X4] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X4); - c->dwarf.loc[UNW_AARCH64_X5] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X5); - c->dwarf.loc[UNW_AARCH64_X6] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X6); - c->dwarf.loc[UNW_AARCH64_X7] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X7); - c->dwarf.loc[UNW_AARCH64_X8] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X8); - c->dwarf.loc[UNW_AARCH64_X9] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X9); - c->dwarf.loc[UNW_AARCH64_X10] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X10); - c->dwarf.loc[UNW_AARCH64_X11] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X11); - c->dwarf.loc[UNW_AARCH64_X12] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X12); - c->dwarf.loc[UNW_AARCH64_X13] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X13); - c->dwarf.loc[UNW_AARCH64_X14] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X14); - c->dwarf.loc[UNW_AARCH64_X15] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X15); - c->dwarf.loc[UNW_AARCH64_X16] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X16); - c->dwarf.loc[UNW_AARCH64_X17] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X17); - c->dwarf.loc[UNW_AARCH64_X18] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X18); - c->dwarf.loc[UNW_AARCH64_X19] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X19); - c->dwarf.loc[UNW_AARCH64_X20] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X20); - c->dwarf.loc[UNW_AARCH64_X21] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X21); - c->dwarf.loc[UNW_AARCH64_X22] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X22); - c->dwarf.loc[UNW_AARCH64_X23] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X23); - c->dwarf.loc[UNW_AARCH64_X24] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X24); - c->dwarf.loc[UNW_AARCH64_X25] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X25); - c->dwarf.loc[UNW_AARCH64_X26] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X26); - c->dwarf.loc[UNW_AARCH64_X27] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X27); - c->dwarf.loc[UNW_AARCH64_X28] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X28); - c->dwarf.loc[UNW_AARCH64_X29] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X29); - c->dwarf.loc[UNW_AARCH64_X30] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X30); - c->dwarf.loc[UNW_AARCH64_SP] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_SP); - c->dwarf.loc[UNW_AARCH64_PC] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_PC); - c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_REG_LOC (&c->dwarf, - UNW_AARCH64_PSTATE); - c->dwarf.loc[UNW_AARCH64_V0] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V0); - c->dwarf.loc[UNW_AARCH64_V1] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V1); - c->dwarf.loc[UNW_AARCH64_V2] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V2); - c->dwarf.loc[UNW_AARCH64_V3] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V3); - c->dwarf.loc[UNW_AARCH64_V4] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V4); - c->dwarf.loc[UNW_AARCH64_V5] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V5); - c->dwarf.loc[UNW_AARCH64_V6] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V6); - c->dwarf.loc[UNW_AARCH64_V7] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V7); - c->dwarf.loc[UNW_AARCH64_V8] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V8); - c->dwarf.loc[UNW_AARCH64_V9] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V9); - c->dwarf.loc[UNW_AARCH64_V10] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V10); - c->dwarf.loc[UNW_AARCH64_V11] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V11); - c->dwarf.loc[UNW_AARCH64_V12] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V12); - c->dwarf.loc[UNW_AARCH64_V13] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V13); - c->dwarf.loc[UNW_AARCH64_V14] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V14); - c->dwarf.loc[UNW_AARCH64_V15] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V15); - c->dwarf.loc[UNW_AARCH64_V16] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V16); - c->dwarf.loc[UNW_AARCH64_V17] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V17); - c->dwarf.loc[UNW_AARCH64_V18] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V18); - c->dwarf.loc[UNW_AARCH64_V19] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V19); - c->dwarf.loc[UNW_AARCH64_V20] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V20); - c->dwarf.loc[UNW_AARCH64_V21] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V21); - c->dwarf.loc[UNW_AARCH64_V22] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V22); - c->dwarf.loc[UNW_AARCH64_V23] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V23); - c->dwarf.loc[UNW_AARCH64_V24] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V24); - c->dwarf.loc[UNW_AARCH64_V25] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V25); - c->dwarf.loc[UNW_AARCH64_V26] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V26); - c->dwarf.loc[UNW_AARCH64_V27] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V27); - c->dwarf.loc[UNW_AARCH64_V28] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V28); - c->dwarf.loc[UNW_AARCH64_V29] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V29); - c->dwarf.loc[UNW_AARCH64_V30] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V30); - c->dwarf.loc[UNW_AARCH64_V31] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V31); - - for (i = UNW_AARCH64_PSTATE + 1; i < UNW_AARCH64_V0; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip); - if (ret < 0) - return ret; - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa); - if (ret < 0) - return ret; - - c->sigcontext_format = AARCH64_SCF_NONE; - c->sigcontext_addr = 0; - c->sigcontext_sp = 0; - c->sigcontext_pc = 0; - - c->dwarf.args_size = 0; - c->dwarf.stash_frames = 0; - c->dwarf.use_prev_instr = use_prev_instr; - c->dwarf.pi_valid = 0; - c->dwarf.pi_is_dynamic = 0; - c->dwarf.hint = 0; - c->dwarf.prev_rs = 0; - - return 0; -} diff --git a/contrib/libunwind/src/aarch64/is_fpreg.c b/contrib/libunwind/src/aarch64/is_fpreg.c deleted file mode 100644 index 7c326932814..00000000000 --- a/contrib/libunwind/src/aarch64/is_fpreg.c +++ /dev/null @@ -1,32 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_is_fpreg (int regnum) -{ - return (regnum >= UNW_AARCH64_V0 && regnum <= UNW_AARCH64_V31); -} diff --git a/contrib/libunwind/src/aarch64/offsets.h b/contrib/libunwind/src/aarch64/offsets.h deleted file mode 100644 index e78251d0a8f..00000000000 --- a/contrib/libunwind/src/aarch64/offsets.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Linux-specific definitions: */ - -/* Define various structure offsets to simplify cross-compilation. */ - -/* Offsets for AArch64 Linux "ucontext_t": */ - -#define LINUX_UC_FLAGS_OFF 0x0 -#define LINUX_UC_LINK_OFF 0x8 -#define LINUX_UC_STACK_OFF 0x10 -#define LINUX_UC_SIGMASK_OFF 0x28 -#define LINUX_UC_MCONTEXT_OFF 0xb0 - -/* Offsets for AArch64 Linux "struct sigcontext": */ - -#define LINUX_SC_FAULTADDRESS_OFF 0x00 -#define LINUX_SC_X0_OFF 0x008 -#define LINUX_SC_X1_OFF 0x010 -#define LINUX_SC_X2_OFF 0x018 -#define LINUX_SC_X3_OFF 0x020 -#define LINUX_SC_X4_OFF 0x028 -#define LINUX_SC_X5_OFF 0x030 -#define LINUX_SC_X6_OFF 0x038 -#define LINUX_SC_X7_OFF 0x040 -#define LINUX_SC_X8_OFF 0x048 -#define LINUX_SC_X9_OFF 0x050 -#define LINUX_SC_X10_OFF 0x058 -#define LINUX_SC_X11_OFF 0x060 -#define LINUX_SC_X12_OFF 0x068 -#define LINUX_SC_X13_OFF 0x070 -#define LINUX_SC_X14_OFF 0x078 -#define LINUX_SC_X15_OFF 0x080 -#define LINUX_SC_X16_OFF 0x088 -#define LINUX_SC_X17_OFF 0x090 -#define LINUX_SC_X18_OFF 0x098 -#define LINUX_SC_X19_OFF 0x0a0 -#define LINUX_SC_X20_OFF 0x0a8 -#define LINUX_SC_X21_OFF 0x0b0 -#define LINUX_SC_X22_OFF 0x0b8 -#define LINUX_SC_X23_OFF 0x0c0 -#define LINUX_SC_X24_OFF 0x0c8 -#define LINUX_SC_X25_OFF 0x0d0 -#define LINUX_SC_X26_OFF 0x0d8 -#define LINUX_SC_X27_OFF 0x0e0 -#define LINUX_SC_X28_OFF 0x0e8 -#define LINUX_SC_X29_OFF 0x0f0 -#define LINUX_SC_X30_OFF 0x0f8 -#define LINUX_SC_SP_OFF 0x100 -#define LINUX_SC_PC_OFF 0x108 -#define LINUX_SC_PSTATE_OFF 0x110 diff --git a/contrib/libunwind/src/aarch64/regname.c b/contrib/libunwind/src/aarch64/regname.c deleted file mode 100644 index 8c9734285d8..00000000000 --- a/contrib/libunwind/src/aarch64/regname.c +++ /dev/null @@ -1,106 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2012 Tommi Rantala - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static const char *const regname[] = - { - [UNW_AARCH64_X0] = "x0", - [UNW_AARCH64_X1] = "x1", - [UNW_AARCH64_X2] = "x2", - [UNW_AARCH64_X3] = "x3", - [UNW_AARCH64_X4] = "x4", - [UNW_AARCH64_X5] = "x5", - [UNW_AARCH64_X6] = "x6", - [UNW_AARCH64_X7] = "x7", - [UNW_AARCH64_X8] = "x8", - [UNW_AARCH64_X9] = "x9", - [UNW_AARCH64_X10] = "x10", - [UNW_AARCH64_X11] = "x11", - [UNW_AARCH64_X12] = "x12", - [UNW_AARCH64_X13] = "x13", - [UNW_AARCH64_X14] = "x14", - [UNW_AARCH64_X15] = "x15", - [UNW_AARCH64_X16] = "ip0", - [UNW_AARCH64_X17] = "ip1", - [UNW_AARCH64_X18] = "x18", - [UNW_AARCH64_X19] = "x19", - [UNW_AARCH64_X20] = "x20", - [UNW_AARCH64_X21] = "x21", - [UNW_AARCH64_X22] = "x22", - [UNW_AARCH64_X23] = "x23", - [UNW_AARCH64_X24] = "x24", - [UNW_AARCH64_X25] = "x25", - [UNW_AARCH64_X26] = "x26", - [UNW_AARCH64_X27] = "x27", - [UNW_AARCH64_X28] = "x28", - [UNW_AARCH64_X29] = "fp", - [UNW_AARCH64_X30] = "lr", - [UNW_AARCH64_SP] = "sp", - [UNW_AARCH64_PC] = "pc", - [UNW_AARCH64_V0] = "v0", - [UNW_AARCH64_V1] = "v1", - [UNW_AARCH64_V2] = "v2", - [UNW_AARCH64_V3] = "v3", - [UNW_AARCH64_V4] = "v4", - [UNW_AARCH64_V5] = "v5", - [UNW_AARCH64_V6] = "v6", - [UNW_AARCH64_V7] = "v7", - [UNW_AARCH64_V8] = "v8", - [UNW_AARCH64_V9] = "v9", - [UNW_AARCH64_V10] = "v10", - [UNW_AARCH64_V11] = "v11", - [UNW_AARCH64_V12] = "v12", - [UNW_AARCH64_V13] = "v13", - [UNW_AARCH64_V14] = "v14", - [UNW_AARCH64_V15] = "v15", - [UNW_AARCH64_V16] = "v16", - [UNW_AARCH64_V17] = "v17", - [UNW_AARCH64_V18] = "v18", - [UNW_AARCH64_V19] = "v19", - [UNW_AARCH64_V20] = "v20", - [UNW_AARCH64_V21] = "v21", - [UNW_AARCH64_V22] = "v22", - [UNW_AARCH64_V23] = "v23", - [UNW_AARCH64_V24] = "v24", - [UNW_AARCH64_V25] = "v25", - [UNW_AARCH64_V26] = "v26", - [UNW_AARCH64_V27] = "v27", - [UNW_AARCH64_V28] = "v28", - [UNW_AARCH64_V29] = "v29", - [UNW_AARCH64_V30] = "v30", - [UNW_AARCH64_V31] = "v31", - [UNW_AARCH64_FPSR] = "fpsr", - [UNW_AARCH64_FPCR] = "fpcr", - }; - -PROTECTED const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < (unw_regnum_t) ARRAY_SIZE (regname) && regname[reg] != NULL) - return regname[reg]; - else - return "???"; -} diff --git a/contrib/libunwind/src/aarch64/siglongjmp.S b/contrib/libunwind/src/aarch64/siglongjmp.S deleted file mode 100644 index 9985c4b4aab..00000000000 --- a/contrib/libunwind/src/aarch64/siglongjmp.S +++ /dev/null @@ -1,12 +0,0 @@ - /* Dummy implementation for now. */ - - .global _UI_siglongjmp_cont - .global _UI_longjmp_cont - -_UI_siglongjmp_cont: -_UI_longjmp_cont: - ret -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",%progbits -#endif diff --git a/contrib/libunwind/src/aarch64/unwind_i.h b/contrib/libunwind/src/aarch64/unwind_i.h deleted file mode 100644 index 3d324c2b08b..00000000000 --- a/contrib/libunwind/src/aarch64/unwind_i.h +++ /dev/null @@ -1,64 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include - -#include - -#include "libunwind_i.h" - -/* DWARF column numbers for AArch64: */ -#define X29 29 -#define FP 29 -#define X30 30 -#define LR 30 -#define SP 31 - -#define aarch64_lock UNW_OBJ(lock) -#define aarch64_local_resume UNW_OBJ(local_resume) -#define aarch64_local_addr_space_init UNW_OBJ(local_addr_space_init) - -extern void aarch64_local_addr_space_init (void); -extern int aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, - void *arg); - -/* By-pass calls to access_mem() when known to be safe. */ -#ifdef UNW_LOCAL_ONLY -# undef ACCESS_MEM_FAST -# define ACCESS_MEM_FAST(ret,validate,cur,addr,to) \ - do { \ - if (unlikely(validate)) \ - (ret) = dwarf_get ((cur), DWARF_MEM_LOC ((cur), (addr)), &(to)); \ - else \ - (ret) = 0, (to) = *(unw_word_t *)(addr); \ - } while (0) -#endif - -#define GET_FPCTX(uc) ((struct fpsimd_context *)(&uc->uc_mcontext.__reserved)) - -#endif /* unwind_i_h */ diff --git a/contrib/libunwind/src/arm/Gapply_reg_state.c b/contrib/libunwind/src/arm/Gapply_reg_state.c deleted file mode 100644 index eec93046f56..00000000000 --- a/contrib/libunwind/src/arm/Gapply_reg_state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); -} diff --git a/contrib/libunwind/src/arm/Gcreate_addr_space.c b/contrib/libunwind/src/arm/Gcreate_addr_space.c deleted file mode 100644 index 4d59a20a7e9..00000000000 --- a/contrib/libunwind/src/arm/Gcreate_addr_space.c +++ /dev/null @@ -1,60 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* - * ARM supports little-endian and big-endian. - */ - if (byte_order != 0 && byte_order != __LITTLE_ENDIAN - && byte_order != __BIG_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - /* Default to little-endian for ARM. */ - if (byte_order == 0 || byte_order == __LITTLE_ENDIAN) - as->big_endian = 0; - else - as->big_endian = 1; - - return as; -#endif -} diff --git a/contrib/libunwind/src/arm/Gex_tables.c b/contrib/libunwind/src/arm/Gex_tables.c deleted file mode 100644 index 3f6b5cfcb58..00000000000 --- a/contrib/libunwind/src/arm/Gex_tables.c +++ /dev/null @@ -1,549 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright 2011 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* This file contains functionality for parsing and interpreting the ARM -specific unwind information. Documentation about the exception handling -ABI for the ARM architecture can be found at: -http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf -*/ - -#include "libunwind_i.h" - -#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f) -#define ARM_EXBUF_COUNT(x) ((x) & 0x0f) -#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x)) - -#define ARM_EXIDX_CANT_UNWIND 0x00000001 -#define ARM_EXIDX_COMPACT 0x80000000 - -#define ARM_EXTBL_OP_FINISH 0xb0 - -enum arm_exbuf_cmd_flags { - ARM_EXIDX_VFP_SHIFT_16 = 1 << 16, - ARM_EXIDX_VFP_DOUBLE = 1 << 17, -}; - -struct arm_cb_data - { - /* in: */ - unw_word_t ip; /* instruction-pointer we're looking for */ - unw_proc_info_t *pi; /* proc-info pointer */ - /* out: */ - unw_dyn_info_t di; /* info about the ARM exidx segment */ - }; - -static inline uint32_t CONST_ATTR -prel31_read (uint32_t prel31) -{ - return ((int32_t)prel31 << 1) >> 1; -} - -static inline int -prel31_to_addr (unw_addr_space_t as, void *arg, unw_word_t prel31, - unw_word_t *val) -{ - unw_word_t offset; - - if ((*as->acc.access_mem)(as, prel31, &offset, 0, arg) < 0) - return -UNW_EINVAL; - - offset = ((long)offset << 1) >> 1; - *val = prel31 + offset; - - return 0; -} - -/** - * Applies the given command onto the new state to the given dwarf_cursor. - */ -HIDDEN int -arm_exidx_apply_cmd (struct arm_exbuf_data *edata, struct dwarf_cursor *c) -{ - int ret = 0; - unsigned i; - - switch (edata->cmd) - { - case ARM_EXIDX_CMD_FINISH: - /* Set LR to PC if not set already. */ - if (DWARF_IS_NULL_LOC (c->loc[UNW_ARM_R15])) - c->loc[UNW_ARM_R15] = c->loc[UNW_ARM_R14]; - /* Set IP. */ - dwarf_get (c, c->loc[UNW_ARM_R15], &c->ip); - break; - case ARM_EXIDX_CMD_DATA_PUSH: - Debug (2, "vsp = vsp - %d\n", edata->data); - c->cfa -= edata->data; - break; - case ARM_EXIDX_CMD_DATA_POP: - Debug (2, "vsp = vsp + %d\n", edata->data); - c->cfa += edata->data; - break; - case ARM_EXIDX_CMD_REG_POP: - for (i = 0; i < 16; i++) - if (edata->data & (1 << i)) - { - Debug (2, "pop {r%d}\n", i); - c->loc[UNW_ARM_R0 + i] = DWARF_LOC (c->cfa, 0); - c->cfa += 4; - } - /* Set cfa in case the SP got popped. */ - if (edata->data & (1 << 13)) - dwarf_get (c, c->loc[UNW_ARM_R13], &c->cfa); - break; - case ARM_EXIDX_CMD_REG_TO_SP: - assert (edata->data < 16); - Debug (2, "vsp = r%d\n", edata->data); - c->loc[UNW_ARM_R13] = c->loc[UNW_ARM_R0 + edata->data]; - dwarf_get (c, c->loc[UNW_ARM_R13], &c->cfa); - break; - case ARM_EXIDX_CMD_VFP_POP: - /* Skip VFP registers, but be sure to adjust stack */ - for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data); - i++) - c->cfa += 8; - if (!(edata->data & ARM_EXIDX_VFP_DOUBLE)) - c->cfa += 4; - break; - case ARM_EXIDX_CMD_WREG_POP: - for (i = ARM_EXBUF_START (edata->data); i <= ARM_EXBUF_END (edata->data); - i++) - c->cfa += 8; - break; - case ARM_EXIDX_CMD_WCGR_POP: - for (i = 0; i < 4; i++) - if (edata->data & (1 << i)) - c->cfa += 4; - break; - case ARM_EXIDX_CMD_REFUSED: - case ARM_EXIDX_CMD_RESERVED: - ret = -1; - break; - } - return ret; -} - -/** - * Decodes the given unwind instructions into arm_exbuf_data and calls - * arm_exidx_apply_cmd that applies the command onto the dwarf_cursor. - */ -HIDDEN int -arm_exidx_decode (const uint8_t *buf, uint8_t len, struct dwarf_cursor *c) -{ -#define READ_OP() *buf++ - const uint8_t *end = buf + len; - int ret; - struct arm_exbuf_data edata; - - assert(buf != NULL); - assert(len > 0); - - while (buf < end) - { - uint8_t op = READ_OP (); - if ((op & 0xc0) == 0x00) - { - edata.cmd = ARM_EXIDX_CMD_DATA_POP; - edata.data = (((int)op & 0x3f) << 2) + 4; - } - else if ((op & 0xc0) == 0x40) - { - edata.cmd = ARM_EXIDX_CMD_DATA_PUSH; - edata.data = (((int)op & 0x3f) << 2) + 4; - } - else if ((op & 0xf0) == 0x80) - { - uint8_t op2 = READ_OP (); - if (op == 0x80 && op2 == 0x00) - edata.cmd = ARM_EXIDX_CMD_REFUSED; - else - { - edata.cmd = ARM_EXIDX_CMD_REG_POP; - edata.data = ((op & 0xf) << 8) | op2; - edata.data = edata.data << 4; - } - } - else if ((op & 0xf0) == 0x90) - { - if (op == 0x9d || op == 0x9f) - edata.cmd = ARM_EXIDX_CMD_RESERVED; - else - { - edata.cmd = ARM_EXIDX_CMD_REG_TO_SP; - edata.data = op & 0x0f; - } - } - else if ((op & 0xf0) == 0xa0) - { - unsigned end = (op & 0x07); - edata.data = (1 << (end + 1)) - 1; - edata.data = edata.data << 4; - if (op & 0x08) - edata.data |= 1 << 14; - edata.cmd = ARM_EXIDX_CMD_REG_POP; - } - else if (op == ARM_EXTBL_OP_FINISH) - { - edata.cmd = ARM_EXIDX_CMD_FINISH; - buf = end; - } - else if (op == 0xb1) - { - uint8_t op2 = READ_OP (); - if (op2 == 0 || (op2 & 0xf0)) - edata.cmd = ARM_EXIDX_CMD_RESERVED; - else - { - edata.cmd = ARM_EXIDX_CMD_REG_POP; - edata.data = op2 & 0x0f; - } - } - else if (op == 0xb2) - { - uint32_t offset = 0; - uint8_t byte, shift = 0; - do - { - byte = READ_OP (); - offset |= (byte & 0x7f) << shift; - shift += 7; - } - while (byte & 0x80); - edata.data = offset * 4 + 0x204; - edata.cmd = ARM_EXIDX_CMD_DATA_POP; - } - else if (op == 0xb3 || op == 0xc8 || op == 0xc9) - { - edata.cmd = ARM_EXIDX_CMD_VFP_POP; - edata.data = READ_OP (); - if (op == 0xc8) - edata.data |= ARM_EXIDX_VFP_SHIFT_16; - if (op != 0xb3) - edata.data |= ARM_EXIDX_VFP_DOUBLE; - } - else if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0) - { - edata.cmd = ARM_EXIDX_CMD_VFP_POP; - edata.data = 0x80 | (op & 0x07); - if ((op & 0xf8) == 0xd0) - edata.data |= ARM_EXIDX_VFP_DOUBLE; - } - else if (op >= 0xc0 && op <= 0xc5) - { - edata.cmd = ARM_EXIDX_CMD_WREG_POP; - edata.data = 0xa0 | (op & 0x07); - } - else if (op == 0xc6) - { - edata.cmd = ARM_EXIDX_CMD_WREG_POP; - edata.data = READ_OP (); - } - else if (op == 0xc7) - { - uint8_t op2 = READ_OP (); - if (op2 == 0 || (op2 & 0xf0)) - edata.cmd = ARM_EXIDX_CMD_RESERVED; - else - { - edata.cmd = ARM_EXIDX_CMD_WCGR_POP; - edata.data = op2 & 0x0f; - } - } - else - edata.cmd = ARM_EXIDX_CMD_RESERVED; - - ret = arm_exidx_apply_cmd (&edata, c); - if (ret < 0) - return ret; - } - return 0; -} - -/** - * Reads the entry from the given cursor and extracts the unwind instructions - * into buf. Returns the number of the extracted unwind insns or - * -UNW_ESTOPUNWIND if the special bit pattern ARM_EXIDX_CANT_UNWIND (0x1) was - * found. - */ -HIDDEN int -arm_exidx_extract (struct dwarf_cursor *c, uint8_t *buf) -{ - int nbuf = 0; - unw_word_t entry = (unw_word_t) c->pi.unwind_info; - unw_word_t addr; - uint32_t data; - - /* An ARM unwind entry consists of a prel31 offset to the start of a - function followed by 31bits of data: - * if set to 0x1: the function cannot be unwound (EXIDX_CANTUNWIND) - * if bit 31 is one: this is a table entry itself (ARM_EXIDX_COMPACT) - * if bit 31 is zero: this is a prel31 offset of the start of the - table entry for this function */ - if (prel31_to_addr(c->as, c->as_arg, entry, &addr) < 0) - return -UNW_EINVAL; - - if ((*c->as->acc.access_mem)(c->as, entry + 4, &data, 0, c->as_arg) < 0) - return -UNW_EINVAL; - - if (data == ARM_EXIDX_CANT_UNWIND) - { - Debug (2, "0x1 [can't unwind]\n"); - nbuf = -UNW_ESTOPUNWIND; - } - else if (data & ARM_EXIDX_COMPACT) - { - Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr, - (data >> 24) & 0x7f, data); - buf[nbuf++] = data >> 16; - buf[nbuf++] = data >> 8; - buf[nbuf++] = data; - } - else - { - unw_word_t extbl_data; - unsigned int n_table_words = 0; - - if (prel31_to_addr(c->as, c->as_arg, entry + 4, &extbl_data) < 0) - return -UNW_EINVAL; - - if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0, c->as_arg) < 0) - return -UNW_EINVAL; - - if (data & ARM_EXIDX_COMPACT) - { - int pers = (data >> 24) & 0x0f; - Debug (2, "%p compact model %d [%8.8x]\n", (void *)addr, pers, data); - if (pers == 1 || pers == 2) - { - n_table_words = (data >> 16) & 0xff; - extbl_data += 4; - } - else - buf[nbuf++] = data >> 16; - buf[nbuf++] = data >> 8; - buf[nbuf++] = data; - } - else - { - unw_word_t pers; - if (prel31_to_addr (c->as, c->as_arg, extbl_data, &pers) < 0) - return -UNW_EINVAL; - Debug (2, "%p Personality routine: %8p\n", (void *)addr, - (void *)pers); - if ((*c->as->acc.access_mem)(c->as, extbl_data + 4, &data, 0, - c->as_arg) < 0) - return -UNW_EINVAL; - n_table_words = data >> 24; - buf[nbuf++] = data >> 16; - buf[nbuf++] = data >> 8; - buf[nbuf++] = data; - extbl_data += 8; - } - assert (n_table_words <= 5); - unsigned j; - for (j = 0; j < n_table_words; j++) - { - if ((*c->as->acc.access_mem)(c->as, extbl_data, &data, 0, - c->as_arg) < 0) - return -UNW_EINVAL; - extbl_data += 4; - buf[nbuf++] = data >> 24; - buf[nbuf++] = data >> 16; - buf[nbuf++] = data >> 8; - buf[nbuf++] = data >> 0; - } - } - - if (nbuf > 0 && buf[nbuf - 1] != ARM_EXTBL_OP_FINISH) - buf[nbuf++] = ARM_EXTBL_OP_FINISH; - - return nbuf; -} - -PROTECTED int -arm_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - /* The .ARM.exidx section contains a sorted list of key-value pairs - - the unwind entries. The 'key' is a prel31 offset to the start of a - function. We binary search this section in order to find the - appropriate unwind entry. */ - unw_word_t first = di->u.rti.table_data; - unw_word_t last = di->u.rti.table_data + di->u.rti.table_len - 8; - unw_word_t entry, val; - - if (prel31_to_addr (as, arg, first, &val) < 0 || ip < val) - return -UNW_ENOINFO; - - if (prel31_to_addr (as, arg, last, &val) < 0) - return -UNW_EINVAL; - - if (ip >= val) - { - entry = last; - - if (prel31_to_addr (as, arg, last, &pi->start_ip) < 0) - return -UNW_EINVAL; - - pi->end_ip = di->end_ip -1; - } - else - { - while (first < last - 8) - { - entry = first + (((last - first) / 8 + 1) >> 1) * 8; - - if (prel31_to_addr (as, arg, entry, &val) < 0) - return -UNW_EINVAL; - - if (ip < val) - last = entry; - else - first = entry; - } - - entry = first; - - if (prel31_to_addr (as, arg, entry, &pi->start_ip) < 0) - return -UNW_EINVAL; - - if (prel31_to_addr (as, arg, entry + 8, &pi->end_ip) < 0) - return -UNW_EINVAL; - - pi->end_ip--; - } - - if (need_unwind_info) - { - pi->unwind_info_size = 8; - pi->unwind_info = (void *) entry; - pi->format = UNW_INFO_FORMAT_ARM_EXIDX; - } - return 0; -} - -PROTECTED int -tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX) - && di->format == UNW_INFO_FORMAT_ARM_EXIDX) - return arm_search_unwind_table (as, ip, di, pi, need_unwind_info, arg); - else if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF) - && di->format != UNW_INFO_FORMAT_ARM_EXIDX) - return dwarf_search_unwind_table (as, ip, di, pi, need_unwind_info, arg); - - return -UNW_ENOINFO; -} - -#ifndef UNW_REMOTE_ONLY -/** - * Callback to dl_iterate_phdr to find infos about the ARM exidx segment. - */ -static int -arm_phdr_cb (struct dl_phdr_info *info, size_t size, void *data) -{ - struct arm_cb_data *cb_data = data; - const Elf_W(Phdr) *p_text = NULL; - const Elf_W(Phdr) *p_arm_exidx = NULL; - const Elf_W(Phdr) *phdr = info->dlpi_phdr; - long n; - - for (n = info->dlpi_phnum; --n >= 0; phdr++) - { - switch (phdr->p_type) - { - case PT_LOAD: - if (cb_data->ip >= phdr->p_vaddr + info->dlpi_addr && - cb_data->ip < phdr->p_vaddr + info->dlpi_addr + phdr->p_memsz) - p_text = phdr; - break; - - case PT_ARM_EXIDX: - p_arm_exidx = phdr; - break; - - default: - break; - } - } - - if (p_text && p_arm_exidx) - { - cb_data->di.format = UNW_INFO_FORMAT_ARM_EXIDX; - cb_data->di.start_ip = p_text->p_vaddr + info->dlpi_addr; - cb_data->di.end_ip = cb_data->di.start_ip + p_text->p_memsz; - cb_data->di.u.rti.name_ptr = (unw_word_t) info->dlpi_name; - cb_data->di.u.rti.table_data = p_arm_exidx->p_vaddr + info->dlpi_addr; - cb_data->di.u.rti.table_len = p_arm_exidx->p_memsz; - return 1; - } - - return 0; -} - -HIDDEN int -arm_find_proc_info (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, int need_unwind_info, void *arg) -{ - int ret = -1; - intrmask_t saved_mask; - - Debug (14, "looking for IP=0x%lx\n", (long) ip); - - if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) - ret = dwarf_find_proc_info (as, ip, pi, need_unwind_info, arg); - - if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) - { - struct arm_cb_data cb_data; - - memset (&cb_data, 0, sizeof (cb_data)); - cb_data.ip = ip; - cb_data.pi = pi; - cb_data.di.format = -1; - - SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); - ret = dl_iterate_phdr (arm_phdr_cb, &cb_data); - SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); - - if (cb_data.di.format != -1) - ret = arm_search_unwind_table (as, ip, &cb_data.di, pi, - need_unwind_info, arg); - else - ret = -UNW_ENOINFO; - } - - return ret; -} - -HIDDEN void -arm_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} -#endif /* !UNW_REMOTE_ONLY */ - diff --git a/contrib/libunwind/src/arm/Gget_proc_info.c b/contrib/libunwind/src/arm/Gget_proc_info.c deleted file mode 100644 index acb78a46440..00000000000 --- a/contrib/libunwind/src/arm/Gget_proc_info.c +++ /dev/null @@ -1,41 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - /* We can only unwind using Dwarf into on ARM: return failure code - if it's not present. */ - ret = dwarf_make_proc_info (&c->dwarf); - if (ret < 0) - return ret; - - *pi = c->dwarf.pi; - return 0; -} diff --git a/contrib/libunwind/src/arm/Gget_save_loc.c b/contrib/libunwind/src/arm/Gget_save_loc.c deleted file mode 100644 index 63b711d855f..00000000000 --- a/contrib/libunwind/src/arm/Gget_save_loc.c +++ /dev/null @@ -1,81 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) -{ - struct cursor *c = (struct cursor *) cursor; - dwarf_loc_t loc; - - loc = DWARF_NULL_LOC; /* default to "not saved" */ - - switch (reg) - { - case UNW_ARM_R0: - case UNW_ARM_R1: - case UNW_ARM_R2: - case UNW_ARM_R3: - case UNW_ARM_R4: - case UNW_ARM_R5: - case UNW_ARM_R6: - case UNW_ARM_R7: - case UNW_ARM_R8: - case UNW_ARM_R9: - case UNW_ARM_R10: - case UNW_ARM_R11: - case UNW_ARM_R12: - case UNW_ARM_R13: - case UNW_ARM_R14: - case UNW_ARM_R15: - loc = c->dwarf.loc[reg - UNW_ARM_R0]; - break; - - default: - break; - } - - memset (sloc, 0, sizeof (*sloc)); - - if (DWARF_IS_NULL_LOC (loc)) - { - sloc->type = UNW_SLT_NONE; - return 0; - } - -#if !defined(UNW_LOCAL_ONLY) - if (DWARF_IS_REG_LOC (loc)) - { - sloc->type = UNW_SLT_REG; - sloc->u.regnum = DWARF_GET_LOC (loc); - } - else -#endif - { - sloc->type = UNW_SLT_MEMORY; - sloc->u.addr = DWARF_GET_LOC (loc); - } - return 0; -} diff --git a/contrib/libunwind/src/arm/Gglobal.c b/contrib/libunwind/src/arm/Gglobal.c deleted file mode 100644 index 7b93fbd89a1..00000000000 --- a/contrib/libunwind/src/arm/Gglobal.c +++ /dev/null @@ -1,65 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "dwarf_i.h" - -HIDDEN define_lock (arm_lock); -HIDDEN int tdep_init_done; - -/* Unwinding methods to use. See UNW_METHOD_ enums */ -HIDDEN int unwi_unwind_method = UNW_ARM_METHOD_ALL; - -HIDDEN void -tdep_init (void) -{ - intrmask_t saved_mask; - - sigfillset (&unwi_full_mask); - - lock_acquire (&arm_lock, saved_mask); - { - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - /* read ARM unwind method setting */ - const char* str = getenv ("UNW_ARM_UNWIND_METHOD"); - if (str) - { - unwi_unwind_method = atoi (str); - } - - mi_init (); - - dwarf_init (); - -#ifndef UNW_REMOTE_ONLY - arm_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - } - out: - lock_release (&arm_lock, saved_mask); -} diff --git a/contrib/libunwind/src/arm/Ginit.c b/contrib/libunwind/src/arm/Ginit.c deleted file mode 100644 index 2d0b2ca8db1..00000000000 --- a/contrib/libunwind/src/arm/Ginit.c +++ /dev/null @@ -1,235 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -PROTECTED unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; - -static inline void * -uc_addr (unw_tdep_context_t *uc, int reg) -{ - if (reg >= UNW_ARM_R0 && reg < UNW_ARM_R0 + 16) - return &uc->regs[reg - UNW_ARM_R0]; - else - return NULL; -} - -# ifdef UNW_LOCAL_ONLY - -HIDDEN void * -tdep_uc_addr (unw_tdep_context_t *uc, int reg) -{ - return uc_addr (uc, reg); -} - -# endif /* UNW_LOCAL_ONLY */ - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - -/* XXX fix me: there is currently no way to locate the dyn-info list - by a remote unwinder. On ia64, this is done via a special - unwind-table entry. Perhaps something similar can be done with - DWARF2 unwind info. */ - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ - *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; - return 0; -} - -#define PAGE_SIZE 4096 -#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1)) - -/* Cache of already validated addresses */ -#define NLGA 4 -static unw_word_t last_good_addr[NLGA]; -static int lga_victim; - -static int -validate_mem (unw_word_t addr) -{ - int i, victim; - size_t len; - - if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr)) - len = PAGE_SIZE; - else - len = PAGE_SIZE * 2; - - addr = PAGE_START(addr); - - if (addr == 0) - return -1; - - for (i = 0; i < NLGA; i++) - { - if (last_good_addr[i] && (addr == last_good_addr[i])) - return 0; - } - - if (msync ((void *) addr, len, MS_ASYNC) == -1) - return -1; - - victim = lga_victim; - for (i = 0; i < NLGA; i++) { - if (!last_good_addr[victim]) { - last_good_addr[victim++] = addr; - return 0; - } - victim = (victim + 1) % NLGA; - } - - /* All slots full. Evict the victim. */ - last_good_addr[victim] = addr; - victim = (victim + 1) % NLGA; - lga_victim = victim; - - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - /* validate address */ - const struct cursor *c = (const struct cursor *) arg; - if (c && validate_mem(addr)) - return -1; - - if (write) - { - Debug (16, "mem[%x] <- %x\n", addr, *val); - *(unw_word_t *) addr = *val; - } - else - { - *val = *(unw_word_t *) addr; - Debug (16, "mem[%x] -> %x\n", addr, *val); - } - return 0; -} - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, - void *arg) -{ - unw_word_t *addr; - unw_tdep_context_t *uc = arg; - - if (unw_is_fpreg (reg)) - goto badreg; - -Debug (16, "reg = %s\n", unw_regname (reg)); - if (!(addr = uc_addr (uc, reg))) - goto badreg; - - if (write) - { - *(unw_word_t *) addr = *val; - Debug (12, "%s <- %x\n", unw_regname (reg), *val); - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "%s -> %x\n", unw_regname (reg), *val); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - unw_tdep_context_t *uc = arg; - unw_fpreg_t *addr; - - if (!unw_is_fpreg (reg)) - goto badreg; - - if (!(addr = uc_addr (uc, reg))) - goto badreg; - - if (write) - { - Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - *(unw_fpreg_t *) addr = *val; - } - else - { - *val = *(unw_fpreg_t *) addr; - Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - /* attempt to access a non-preserved register */ - return -UNW_EBADREG; -} - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp); -} - -HIDDEN void -arm_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; - local_addr_space.acc.find_proc_info = arm_find_proc_info; - local_addr_space.acc.put_unwind_info = arm_put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = arm_local_resume; - local_addr_space.acc.get_proc_name = get_static_proc_name; - unw_flush_cache (&local_addr_space, 0, 0); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/arm/Ginit_local.c b/contrib/libunwind/src/arm/Ginit_local.c deleted file mode 100644 index 65941c369e4..00000000000 --- a/contrib/libunwind/src/arm/Ginit_local.c +++ /dev/null @@ -1,78 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright 2011 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "init.h" - -#ifdef UNW_REMOTE_ONLY - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) -{ - return -UNW_EINVAL; -} - -#else /* !UNW_REMOTE_ONLY */ - -static int -unw_init_local_common (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr) -{ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = unw_local_addr_space; - c->dwarf.as_arg = uc; - - return common_init (c, use_prev_instr); -} - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) -{ - return unw_init_local_common(cursor, uc, 1); -} - -PROTECTED int -unw_init_local2 (unw_cursor_t *cursor, unw_context_t *uc, int flag) -{ - if (!flag) - { - return unw_init_local_common(cursor, uc, 1); - } - else if (flag == UNW_INIT_SIGNAL_FRAME) - { - return unw_init_local_common(cursor, uc, 0); - } - else - { - return -UNW_EINVAL; - } -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/arm/Ginit_remote.c b/contrib/libunwind/src/arm/Ginit_remote.c deleted file mode 100644 index f284e994f4b..00000000000 --- a/contrib/libunwind/src/arm/Ginit_remote.c +++ /dev/null @@ -1,45 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "init.h" -#include "unwind_i.h" - -PROTECTED int -unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) -{ -#ifdef UNW_LOCAL_ONLY - return -UNW_EINVAL; -#else /* !UNW_LOCAL_ONLY */ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = as; - c->dwarf.as_arg = as_arg; - return common_init (c, 0); -#endif /* !UNW_LOCAL_ONLY */ -} diff --git a/contrib/libunwind/src/arm/Gos-freebsd.c b/contrib/libunwind/src/arm/Gos-freebsd.c deleted file mode 100644 index 3b9d2c3eb52..00000000000 --- a/contrib/libunwind/src/arm/Gos-freebsd.c +++ /dev/null @@ -1,129 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright 2011 Linaro Limited - Copyright (C) 2012 Tommi Rantala - Copyright 2015 The FreeBSD Foundation - - Portions of this software were developed by Konstantin Belousov - under sponsorship from the FreeBSD Foundation. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include -#include "unwind_i.h" -#include "offsets.h" -#include "ex_tables.h" - -PROTECTED int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret, fmt; - unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; - struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); - - if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) - return -UNW_EUNSPEC; - fmt = unw_is_signal_frame(cursor); - - c->dwarf.pi_valid = 0; - - if (fmt == UNW_ARM_FRAME_SYSCALL) - { - c->sigcontext_format = ARM_SCF_FREEBSD_SYSCALL; - c->frame_info.frame_type = UNW_ARM_FRAME_SYSCALL; - c->frame_info.cfa_reg_offset = 0; - c->dwarf.loc[UNW_ARM_R7] = c->dwarf.loc[UNW_ARM_R12]; - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R14], &c->dwarf.ip); - return 1; - } - - c->sigcontext_format = ARM_SCF_FREEBSD_SIGFRAME; - sc_addr = sp_addr; - - /* Save the SP and PC to be able to return execution at this point - later in time (unw_resume). */ - c->sigcontext_sp = c->dwarf.cfa; - c->sigcontext_pc = c->dwarf.ip; - - c->sigcontext_addr = sc_addr; - c->frame_info.frame_type = UNW_ARM_FRAME_SIGRETURN; - c->frame_info.cfa_reg_offset = sc_addr - sp_addr; - - /* Update the dwarf cursor. - Set the location of the registers to the corresponding addresses of the - uc_mcontext / sigcontext structure contents. */ -#define ROFF(n) (FREEBSD_SC_UCONTEXT_OFF + FREEBSD_UC_MCONTEXT_OFF + \ - FREEBSD_MC_R0_OFF + (n) * 4) -#define SL(n) \ - c->dwarf.loc[UNW_ARM_R ## n] = DWARF_LOC (sc_addr + ROFF(n), 0); - SL(0); SL(1); SL(2); SL(3); SL(4); SL(5); SL(6); SL(7); - SL(8); SL(9); SL(10); SL(11); SL(12); SL(13); SL(14); SL(15); -#undef SL -#undef ROFF - - /* Set SP/CFA and PC/IP. */ - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R13], &c->dwarf.cfa); - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip); - - return 1; -} - -/* Returns 1 in case of a non-RT signal frame and 2 in case of a RT signal - frame. */ -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, w1, w2, w3, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - ip = c->dwarf.ip; - - if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0) - return ret; - if ((ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) - return ret; - if ((ret = (*a->access_mem) (as, ip + 8, &w2, 0, arg)) < 0) - return ret; - if ((ret = (*a->access_mem) (as, ip + 12, &w3, 0, arg)) < 0) - return ret; - - if (w0 == 0xe1a0000d && w1 == 0xe2800040 && w2 == 0xe59f700c && - w3 == 0xef0001a1) - return UNW_ARM_FRAME_SIGRETURN; - - if ((ret = (*a->access_mem) (as, ip - 4, &w0, 0, arg)) < 0) - return ret; - if (w0 == 0xef000000) - return UNW_ARM_FRAME_SYSCALL; - - return 0; -} diff --git a/contrib/libunwind/src/arm/Gos-linux.c b/contrib/libunwind/src/arm/Gos-linux.c deleted file mode 100644 index 585c2014fde..00000000000 --- a/contrib/libunwind/src/arm/Gos-linux.c +++ /dev/null @@ -1,182 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright 2011 Linaro Limited - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include -#include "unwind_i.h" -#include "offsets.h" - -PROTECTED int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; - struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); - - if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) - return -UNW_EUNSPEC; - - /* Obtain signal frame type (non-RT or RT). */ - ret = unw_is_signal_frame (cursor); - - /* Save the SP and PC to be able to return execution at this point - later in time (unw_resume). */ - c->sigcontext_sp = c->dwarf.cfa; - c->sigcontext_pc = c->dwarf.ip; - - /* Since kernel version 2.6.18 the non-RT signal frame starts with a - ucontext while the RT signal frame starts with a siginfo, followed - by a sigframe whose first element is an ucontext. - Prior 2.6.18 the non-RT signal frame starts with a sigcontext while - the RT signal frame starts with two pointers followed by a siginfo - and an ucontext. The first pointer points to the start of the siginfo - structure and the second one to the ucontext structure. */ - - if (ret == 1) - { - /* Handle non-RT signal frames. Check if the first word on the stack - is the magic number. */ - if (sp == 0x5ac3c35a) - { - c->sigcontext_format = ARM_SCF_LINUX_SIGFRAME; - sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF; - } - else - { - c->sigcontext_format = ARM_SCF_LINUX_OLD_SIGFRAME; - sc_addr = sp_addr; - } - } - else if (ret == 2) - { - /* Handle RT signal frames. Check if the first word on the stack is a - pointer to the siginfo structure. */ - if (sp == sp_addr + 8) - { - c->sigcontext_format = ARM_SCF_LINUX_OLD_RT_SIGFRAME; - sc_addr = sp_addr + 8 + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; - } - else - { - c->sigcontext_format = ARM_SCF_LINUX_RT_SIGFRAME; - sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; - } - } - else - return -UNW_EUNSPEC; - - c->sigcontext_addr = sc_addr; - c->frame_info.frame_type = UNW_ARM_FRAME_SIGRETURN; - c->frame_info.cfa_reg_offset = sc_addr - sp_addr; - - /* Update the dwarf cursor. - Set the location of the registers to the corresponding addresses of the - uc_mcontext / sigcontext structure contents. */ - c->dwarf.loc[UNW_ARM_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); - c->dwarf.loc[UNW_ARM_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); - c->dwarf.loc[UNW_ARM_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); - c->dwarf.loc[UNW_ARM_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); - c->dwarf.loc[UNW_ARM_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); - c->dwarf.loc[UNW_ARM_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); - c->dwarf.loc[UNW_ARM_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); - c->dwarf.loc[UNW_ARM_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); - c->dwarf.loc[UNW_ARM_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); - c->dwarf.loc[UNW_ARM_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); - c->dwarf.loc[UNW_ARM_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); - c->dwarf.loc[UNW_ARM_R11] = DWARF_LOC (sc_addr + LINUX_SC_FP_OFF, 0); - c->dwarf.loc[UNW_ARM_R12] = DWARF_LOC (sc_addr + LINUX_SC_IP_OFF, 0); - c->dwarf.loc[UNW_ARM_R13] = DWARF_LOC (sc_addr + LINUX_SC_SP_OFF, 0); - c->dwarf.loc[UNW_ARM_R14] = DWARF_LOC (sc_addr + LINUX_SC_LR_OFF, 0); - c->dwarf.loc[UNW_ARM_R15] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); - - /* Set SP/CFA and PC/IP. */ - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R13], &c->dwarf.cfa); - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip); - - c->dwarf.pi_valid = 0; - - return 1; -} - -#define ARM_NR_sigreturn 119 -#define ARM_NR_rt_sigreturn 173 -#define ARM_NR_OABI_SYSCALL_BASE 0x900000 - -/* ARM EABI sigreturn (the syscall number is loaded into r7) */ -#define MOV_R7_SIGRETURN (0xe3a07000UL | ARM_NR_sigreturn) -#define MOV_R7_RT_SIGRETURN (0xe3a07000UL | ARM_NR_rt_sigreturn) - -/* ARM OABI sigreturn (using SWI) */ -#define ARM_SIGRETURN \ - (0xef000000UL | ARM_NR_sigreturn | ARM_NR_OABI_SYSCALL_BASE) -#define ARM_RT_SIGRETURN \ - (0xef000000UL | ARM_NR_rt_sigreturn | ARM_NR_OABI_SYSCALL_BASE) - -/* Thumb sigreturn (two insns, syscall number is loaded into r7) */ -#define THUMB_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_sigreturn) -#define THUMB_RT_SIGRETURN (0xdf00UL << 16 | 0x2700 | ARM_NR_rt_sigreturn) - -/* Thumb2 sigreturn (mov.w r7, $SYS_ify(rt_sigreturn/sigreturn)) */ -#define THUMB2_SIGRETURN (((0x0700 | ARM_NR_sigreturn) << 16) | \ - 0xf04f) -#define THUMB2_RT_SIGRETURN (((0x0700 | ARM_NR_rt_sigreturn) << 16) | \ - 0xf04f) -/* TODO: with different toolchains, there are a lot more possibilities */ - -/* Returns 1 in case of a non-RT signal frame and 2 in case of a RT signal - frame. */ -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - /* The least bit denotes thumb/arm mode. Do not read there. */ - ip = c->dwarf.ip & ~0x1; - - if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0) - return ret; - - /* Return 1 if the IP points to a non-RT sigreturn sequence. */ - if (w0 == MOV_R7_SIGRETURN || w0 == ARM_SIGRETURN || w0 == THUMB_SIGRETURN - || w0 == THUMB2_SIGRETURN) - return 1; - /* Return 2 if the IP points to a RT sigreturn sequence. */ - else if (w0 == MOV_R7_RT_SIGRETURN || w0 == ARM_RT_SIGRETURN - || w0 == THUMB_RT_SIGRETURN || w0 == THUMB2_RT_SIGRETURN) - return 2; - - return 0; -} diff --git a/contrib/libunwind/src/arm/Gos-other.c b/contrib/libunwind/src/arm/Gos-other.c deleted file mode 100644 index 66f38b1dace..00000000000 --- a/contrib/libunwind/src/arm/Gos-other.c +++ /dev/null @@ -1,48 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright 2011 Linaro Limited - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include -#include "unwind_i.h" -#include "offsets.h" - -PROTECTED int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ - return -UNW_EUNSPEC; -} - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ -#if defined(__QNX__) - /* Not supported yet */ - return 0; -#else - printf ("%s: implement me\n", __FUNCTION__); - return -UNW_ENOINFO; -#endif -} diff --git a/contrib/libunwind/src/arm/Greg_states_iterate.c b/contrib/libunwind/src/arm/Greg_states_iterate.c deleted file mode 100644 index a39837a1781..00000000000 --- a/contrib/libunwind/src/arm/Greg_states_iterate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_reg_states_iterate (&c->dwarf, cb, token); -} diff --git a/contrib/libunwind/src/arm/Gregs.c b/contrib/libunwind/src/arm/Gregs.c deleted file mode 100644 index 0d52f0b2225..00000000000 --- a/contrib/libunwind/src/arm/Gregs.c +++ /dev/null @@ -1,83 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - dwarf_loc_t loc = DWARF_NULL_LOC; - - switch (reg) - { - case UNW_ARM_R15: - if (write) - c->dwarf.ip = *valp; /* update the IP cache */ - case UNW_ARM_R0: - case UNW_ARM_R1: - case UNW_ARM_R2: - case UNW_ARM_R3: - case UNW_ARM_R4: - case UNW_ARM_R5: - case UNW_ARM_R6: - case UNW_ARM_R7: - case UNW_ARM_R8: - case UNW_ARM_R9: - case UNW_ARM_R10: - case UNW_ARM_R11: - case UNW_ARM_R12: - case UNW_ARM_R14: - loc = c->dwarf.loc[reg - UNW_ARM_R0]; - break; - - case UNW_ARM_R13: - case UNW_ARM_CFA: - if (write) - return -UNW_EREADONLYREG; - *valp = c->dwarf.cfa; - return 0; - - /* FIXME: Initialise coprocessor & shadow registers? */ - - default: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; - } - - if (write) - return dwarf_put (&c->dwarf, loc, *valp); - else - return dwarf_get (&c->dwarf, loc, valp); -} - -/* FIXME for ARM. */ - -HIDDEN int -tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, - int write) -{ - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} diff --git a/contrib/libunwind/src/arm/Gresume.c b/contrib/libunwind/src/arm/Gresume.c deleted file mode 100644 index 9fe264ea22f..00000000000 --- a/contrib/libunwind/src/arm/Gresume.c +++ /dev/null @@ -1,154 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright 2011 Linaro Limited - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" - -#ifndef UNW_REMOTE_ONLY - -HIDDEN inline int -arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ -#ifdef __linux__ - struct cursor *c = (struct cursor *) cursor; - unw_tdep_context_t *uc = c->dwarf.as_arg; - - if (c->sigcontext_format == ARM_SCF_NONE) - { - /* Since there are no signals involved here we restore the non scratch - registers only. */ - unsigned long regs[10]; - regs[0] = uc->regs[4]; - regs[1] = uc->regs[5]; - regs[2] = uc->regs[6]; - regs[3] = uc->regs[7]; - regs[4] = uc->regs[8]; - regs[5] = uc->regs[9]; - regs[6] = uc->regs[10]; - regs[7] = uc->regs[11]; /* FP */ - regs[8] = uc->regs[13]; /* SP */ - regs[9] = uc->regs[14]; /* LR */ - - struct regs_overlay { - char x[sizeof(regs)]; - }; - - asm __volatile__ ( - "ldmia %0, {r4-r12, lr}\n" - "mov sp, r12\n" - "bx lr\n" - : : "r" (regs), - "m" (*(struct regs_overlay *)regs) - ); - } - else - { - /* In case a signal frame is involved, we're using its trampoline which - calls sigreturn. */ - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - sc->arm_r0 = uc->regs[0]; - sc->arm_r1 = uc->regs[1]; - sc->arm_r2 = uc->regs[2]; - sc->arm_r3 = uc->regs[3]; - sc->arm_r4 = uc->regs[4]; - sc->arm_r5 = uc->regs[5]; - sc->arm_r6 = uc->regs[6]; - sc->arm_r7 = uc->regs[7]; - sc->arm_r8 = uc->regs[8]; - sc->arm_r9 = uc->regs[9]; - sc->arm_r10 = uc->regs[10]; - sc->arm_fp = uc->regs[11]; /* FP */ - sc->arm_ip = uc->regs[12]; /* IP */ - sc->arm_sp = uc->regs[13]; /* SP */ - sc->arm_lr = uc->regs[14]; /* LR */ - sc->arm_pc = uc->regs[15]; /* PC */ - /* clear the ITSTATE bits. */ - sc->arm_cpsr &= 0xf9ff03ffUL; - - /* Set the SP and the PC in order to continue execution at the modified - trampoline which restores the signal mask and the registers. */ - asm __volatile__ ( - "mov sp, %0\n" - "bx %1\n" - : : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc) - ); - } - unreachable(); -#else - printf ("%s: implement me\n", __FUNCTION__); -#endif - return -UNW_EINVAL; -} - -#endif /* !UNW_REMOTE_ONLY */ - -static inline void -establish_machine_state (struct cursor *c) -{ - unw_addr_space_t as = c->dwarf.as; - void *arg = c->dwarf.as_arg; - unw_fpreg_t fpval; - unw_word_t val; - int reg; - - Debug (8, "copying out cursor state\n"); - - for (reg = 0; reg <= UNW_REG_LAST; ++reg) - { - Debug (16, "copying %s %d\n", unw_regname (reg), reg); - if (unw_is_fpreg (reg)) - { - if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) - as->acc.access_fpreg (as, reg, &fpval, 1, arg); - } - else - { - if (tdep_access_reg (c, reg, &val, 0) >= 0) - as->acc.access_reg (as, reg, &val, 1, arg); - } - } -} - -PROTECTED int -unw_resume (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - - Debug (1, "(cursor=%p)\n", c); - - if (!c->dwarf.ip) - { - /* This can happen easily when the frame-chain gets truncated - due to bad or missing unwind-info. */ - Debug (1, "refusing to resume execution at address 0\n"); - return -UNW_EINVAL; - } - - establish_machine_state (c); - - return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, - c->dwarf.as_arg); -} diff --git a/contrib/libunwind/src/arm/Gstash_frame.c b/contrib/libunwind/src/arm/Gstash_frame.c deleted file mode 100644 index c5a76b86d0a..00000000000 --- a/contrib/libunwind/src/arm/Gstash_frame.c +++ /dev/null @@ -1,90 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY - Copyright (C) 2014 CERN and Aalto University - Contributed by Filip Nyback - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -HIDDEN void -tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) -{ - struct cursor *c = (struct cursor *) dwarf_to_cursor (d); - unw_tdep_frame_t *f = &c->frame_info; - - Debug (4, "ip=0x%x cfa=0x%x type %d cfa [where=%d val=%d] cfaoff=%d" - " ra=0x%x r7 [where=%d val=%d @0x%x] lr [where=%d val=%d @0x%x] " - "sp [where=%d val=%d @0x%x]\n", - d->ip, d->cfa, f->frame_type, - rs->reg.where[DWARF_CFA_REG_COLUMN], - rs->reg.val[DWARF_CFA_REG_COLUMN], - rs->reg.val[DWARF_CFA_OFF_COLUMN], - DWARF_GET_LOC(d->loc[rs->ret_addr_column]), - rs->reg.where[R7], rs->reg.val[R7], DWARF_GET_LOC(d->loc[R7]), - rs->reg.where[LR], rs->reg.val[LR], DWARF_GET_LOC(d->loc[LR]), - rs->reg.where[SP], rs->reg.val[SP], DWARF_GET_LOC(d->loc[SP])); - - /* A standard frame is defined as: - - CFA is register-relative offset off R7 or SP; - - Return address is saved in LR; - - R7 is unsaved or saved at CFA+offset, offset != -1; - - LR is unsaved or saved at CFA+offset, offset != -1; - - SP is unsaved or saved at CFA+offset, offset != -1. */ - if (f->frame_type == UNW_ARM_FRAME_OTHER - && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG) - && (rs->reg.val[DWARF_CFA_REG_COLUMN] == R7 - || rs->reg.val[DWARF_CFA_REG_COLUMN] == SP) - && labs(rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 29) - && rs->ret_addr_column == LR - && (rs->reg.where[R7] == DWARF_WHERE_UNDEF - || rs->reg.where[R7] == DWARF_WHERE_SAME - || (rs->reg.where[R7] == DWARF_WHERE_CFAREL - && labs(rs->reg.val[R7]) < (1 << 29) - && rs->reg.val[R7]+1 != 0)) - && (rs->reg.where[LR] == DWARF_WHERE_UNDEF - || rs->reg.where[LR] == DWARF_WHERE_SAME - || (rs->reg.where[LR] == DWARF_WHERE_CFAREL - && labs(rs->reg.val[LR]) < (1 << 29) - && rs->reg.val[LR]+1 != 0)) - && (rs->reg.where[SP] == DWARF_WHERE_UNDEF - || rs->reg.where[SP] == DWARF_WHERE_SAME - || (rs->reg.where[SP] == DWARF_WHERE_CFAREL - && labs(rs->reg.val[SP]) < (1 << 29) - && rs->reg.val[SP]+1 != 0))) - { - /* Save information for a standard frame. */ - f->frame_type = UNW_ARM_FRAME_STANDARD; - f->cfa_reg_sp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == SP); - f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN]; - if (rs->reg.where[R7] == DWARF_WHERE_CFAREL) - f->r7_cfa_offset = rs->reg.val[R7]; - if (rs->reg.where[LR] == DWARF_WHERE_CFAREL) - f->lr_cfa_offset = rs->reg.val[LR]; - if (rs->reg.where[SP] == DWARF_WHERE_CFAREL) - f->sp_cfa_offset = rs->reg.val[SP]; - Debug (4, " standard frame\n"); - } - else - Debug (4, " unusual frame\n"); -} - diff --git a/contrib/libunwind/src/arm/Gstep.c b/contrib/libunwind/src/arm/Gstep.c deleted file mode 100644 index 6679455ece2..00000000000 --- a/contrib/libunwind/src/arm/Gstep.c +++ /dev/null @@ -1,189 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright 2011 Linaro Limited - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" -#include "ex_tables.h" - -#include - -#define arm_exidx_step UNW_OBJ(arm_exidx_step) - -static inline int -arm_exidx_step (struct cursor *c) -{ - unw_word_t old_ip, old_cfa; - uint8_t buf[32]; - int ret; - - old_ip = c->dwarf.ip; - old_cfa = c->dwarf.cfa; - - /* mark PC unsaved */ - c->dwarf.loc[UNW_ARM_R15] = DWARF_NULL_LOC; - - /* check dynamic info first --- it overrides everything else */ - ret = unwi_find_dynamic_proc_info (c->dwarf.as, c->dwarf.ip, &c->dwarf.pi, 1, - c->dwarf.as_arg); - if (ret == -UNW_ENOINFO) - { - if ((ret = tdep_find_proc_info (&c->dwarf, c->dwarf.ip, 1)) < 0) - return ret; - } - - if (c->dwarf.pi.format != UNW_INFO_FORMAT_ARM_EXIDX) - return -UNW_ENOINFO; - - ret = arm_exidx_extract (&c->dwarf, buf); - if (ret == -UNW_ESTOPUNWIND) - return 0; - else if (ret < 0) - return ret; - - ret = arm_exidx_decode (buf, ret, &c->dwarf); - if (ret < 0) - return ret; - - if (c->dwarf.ip == old_ip && c->dwarf.cfa == old_cfa) - { - Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", - __FUNCTION__, (long) c->dwarf.ip); - return -UNW_EBADFRAME; - } - - c->dwarf.pi_valid = 0; - - return (c->dwarf.ip == 0) ? 0 : 1; -} - -PROTECTED int -unw_step (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret = -UNW_EUNSPEC; - - Debug (1, "(cursor=%p)\n", c); - - /* Check if this is a signal frame. */ - if (unw_is_signal_frame (cursor) > 0) - return unw_handle_signal_frame (cursor); - -#ifdef CONFIG_DEBUG_FRAME - /* First, try DWARF-based unwinding. */ - if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) - { - ret = dwarf_step (&c->dwarf); - Debug(1, "dwarf_step()=%d\n", ret); - - if (likely (ret > 0)) - return 1; - else if (unlikely (ret == -UNW_ESTOPUNWIND)) - return ret; - - if (ret < 0 && ret != -UNW_ENOINFO) - { - Debug (2, "returning %d\n", ret); - return ret; - } - } -#endif /* CONFIG_DEBUG_FRAME */ - - /* Next, try extbl-based unwinding. */ - if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX)) - { - ret = arm_exidx_step (c); - if (ret > 0) - return 1; - if (ret == -UNW_ESTOPUNWIND || ret == 0) - return ret; - } - - /* Fall back on APCS frame parsing. - Note: This won't work in case the ARM EABI is used. */ -#ifdef __FreeBSD__ - if (0) -#else - if (unlikely (ret < 0)) -#endif - { - if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME)) - { - Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); - ret = UNW_ESUCCESS; - /* DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */ - unw_word_t instr, i; - dwarf_loc_t ip_loc, fp_loc; - unw_word_t frame; - /* Mark all registers unsaved, since we don't know where - they are saved (if at all), except for the EBP and - EIP. */ - if (dwarf_get(&c->dwarf, c->dwarf.loc[UNW_ARM_R11], &frame) < 0) - { - return 0; - } - for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) { - c->dwarf.loc[i] = DWARF_NULL_LOC; - } - if (frame) - { - if (dwarf_get(&c->dwarf, DWARF_LOC(frame, 0), &instr) < 0) - { - return 0; - } - instr -= 8; - if (dwarf_get(&c->dwarf, DWARF_LOC(instr, 0), &instr) < 0) - { - return 0; - } - if ((instr & 0xFFFFD800) == 0xE92DD800) - { - /* Standard APCS frame. */ - ip_loc = DWARF_LOC(frame - 4, 0); - fp_loc = DWARF_LOC(frame - 12, 0); - } - else - { - /* Codesourcery optimized normal frame. */ - ip_loc = DWARF_LOC(frame, 0); - fp_loc = DWARF_LOC(frame - 4, 0); - } - if (dwarf_get(&c->dwarf, ip_loc, &c->dwarf.ip) < 0) - { - return 0; - } - c->dwarf.loc[UNW_ARM_R12] = ip_loc; - c->dwarf.loc[UNW_ARM_R11] = fp_loc; - c->dwarf.pi_valid = 0; - Debug(15, "ip=%x\n", c->dwarf.ip); - } - else - { - ret = -UNW_ENOINFO; - } - } - } - return ret == -UNW_ENOINFO ? 0 : ret; -} diff --git a/contrib/libunwind/src/arm/Gtrace.c b/contrib/libunwind/src/arm/Gtrace.c deleted file mode 100644 index 2f277520b36..00000000000 --- a/contrib/libunwind/src/arm/Gtrace.c +++ /dev/null @@ -1,557 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY - Copyright (C) 2014 CERN and Aalto University - Contributed by Filip Nyback - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" -#include -#include - -#pragma weak pthread_once -#pragma weak pthread_key_create -#pragma weak pthread_getspecific -#pragma weak pthread_setspecific - -/* Initial hash table size. Table expands by 2 bits (times four). */ -#define HASH_MIN_BITS 14 - -typedef struct -{ - unw_tdep_frame_t *frames; - size_t log_size; - size_t used; - size_t dtor_count; /* Counts how many times our destructor has already - been called. */ -} unw_trace_cache_t; - -static const unw_tdep_frame_t empty_frame = { 0, UNW_ARM_FRAME_OTHER, -1, -1, 0, -1, -1, -1 }; -static define_lock (trace_init_lock); -static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT; -static sig_atomic_t trace_cache_once_happen; -static pthread_key_t trace_cache_key; -static struct mempool trace_cache_pool; -static __thread unw_trace_cache_t *tls_cache; -static __thread int tls_cache_destroyed; - -/* Free memory for a thread's trace cache. */ -static void -trace_cache_free (void *arg) -{ - unw_trace_cache_t *cache = arg; - if (++cache->dtor_count < PTHREAD_DESTRUCTOR_ITERATIONS) - { - /* Not yet our turn to get destroyed. Re-install ourselves into the key. */ - pthread_setspecific(trace_cache_key, cache); - Debug(5, "delayed freeing cache %p (%zx to go)\n", cache, - PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count); - return; - } - tls_cache_destroyed = 1; - tls_cache = NULL; - munmap (cache->frames, (1u << cache->log_size) * sizeof(unw_tdep_frame_t)); - mempool_free (&trace_cache_pool, cache); - Debug(5, "freed cache %p\n", cache); -} - -/* Initialise frame tracing for threaded use. */ -static void -trace_cache_init_once (void) -{ - pthread_key_create (&trace_cache_key, &trace_cache_free); - mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); - trace_cache_once_happen = 1; -} - -static unw_tdep_frame_t * -trace_cache_buckets (size_t n) -{ - unw_tdep_frame_t *frames; - size_t i; - - GET_MEMORY(frames, n * sizeof (unw_tdep_frame_t)); - if (likely(frames != NULL)) - for (i = 0; i < n; ++i) - frames[i] = empty_frame; - - return frames; -} - -/* Allocate and initialise hash table for frame cache lookups. - Returns the cache initialised with (1u << HASH_LOW_BITS) hash - buckets, or NULL if there was a memory allocation problem. */ -static unw_trace_cache_t * -trace_cache_create (void) -{ - unw_trace_cache_t *cache; - - if (tls_cache_destroyed) - { - /* The current thread is in the process of exiting. Don't recreate - cache, as we wouldn't have another chance to free it. */ - Debug(5, "refusing to reallocate cache: " - "thread-locals are being deallocated\n"); - return NULL; - } - - if (! (cache = mempool_alloc(&trace_cache_pool))) - { - Debug(5, "failed to allocate cache\n"); - return NULL; - } - - if (! (cache->frames = trace_cache_buckets(1u << HASH_MIN_BITS))) - { - Debug(5, "failed to allocate buckets\n"); - mempool_free(&trace_cache_pool, cache); - return NULL; - } - - cache->log_size = HASH_MIN_BITS; - cache->used = 0; - cache->dtor_count = 0; - tls_cache_destroyed = 0; /* Paranoia: should already be 0. */ - Debug(5, "allocated cache %p\n", cache); - return cache; -} - -/* Expand the hash table in the frame cache if possible. This always - quadruples the hash size, and clears all previous frame entries. */ -static int -trace_cache_expand (unw_trace_cache_t *cache) -{ - size_t old_size = (1u << cache->log_size); - size_t new_log_size = cache->log_size + 2; - unw_tdep_frame_t *new_frames = trace_cache_buckets (1u << new_log_size); - - if (unlikely(! new_frames)) - { - Debug(5, "failed to expand cache to 2^%u buckets\n", new_log_size); - return -UNW_ENOMEM; - } - - Debug(5, "expanded cache from 2^%u to 2^%u buckets\n", cache->log_size, - new_log_size); - munmap(cache->frames, old_size * sizeof(unw_tdep_frame_t)); - cache->frames = new_frames; - cache->log_size = new_log_size; - cache->used = 0; - return 0; -} - -static unw_trace_cache_t * -trace_cache_get_unthreaded (void) -{ - unw_trace_cache_t *cache; - intrmask_t saved_mask; - static unw_trace_cache_t *global_cache = NULL; - lock_acquire (&trace_init_lock, saved_mask); - if (! global_cache) - { - mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); - global_cache = trace_cache_create (); - } - cache = global_cache; - lock_release (&trace_init_lock, saved_mask); - Debug(5, "using cache %p\n", cache); - return cache; -} - -/* Get the frame cache for the current thread. Create it if there is none. */ -static unw_trace_cache_t * -trace_cache_get (void) -{ - unw_trace_cache_t *cache; - if (likely (pthread_once != NULL)) - { - pthread_once(&trace_cache_once, &trace_cache_init_once); - if (!trace_cache_once_happen) - { - return trace_cache_get_unthreaded(); - } - if (! (cache = tls_cache)) - { - cache = trace_cache_create(); - pthread_setspecific(trace_cache_key, cache); - tls_cache = cache; - } - Debug(5, "using cache %p\n", cache); - return cache; - } - else - { - return trace_cache_get_unthreaded(); - } -} - -/* Initialise frame properties for address cache slot F at address - PC using current CFA, R7 and SP values. Modifies CURSOR to - that location, performs one unw_step(), and fills F with what - was discovered about the location. Returns F. - - FIXME: This probably should tell DWARF handling to never evaluate - or use registers other than R7, SP and PC in case there is - highly unusual unwind info which uses these creatively. */ -static unw_tdep_frame_t * -trace_init_addr (unw_tdep_frame_t *f, - unw_cursor_t *cursor, - unw_word_t cfa, - unw_word_t pc, - unw_word_t r7, - unw_word_t sp) -{ - struct cursor *c = (struct cursor *) cursor; - struct dwarf_cursor *d = &c->dwarf; - int ret = -UNW_EINVAL; - - /* Initialise frame properties: unknown, not last. */ - f->virtual_address = pc; - f->frame_type = UNW_ARM_FRAME_OTHER; - f->last_frame = 0; - f->cfa_reg_sp = -1; - f->cfa_reg_offset = 0; - f->r7_cfa_offset = -1; - f->lr_cfa_offset = -1; - f->sp_cfa_offset = -1; - - /* Reinitialise cursor to this instruction - but undo next/prev RIP - adjustment because unw_step will redo it - and force PC, R7 and - SP into register locations (=~ ucontext we keep), then set - their desired values. Then perform the step. */ - d->ip = pc + d->use_prev_instr; - d->cfa = cfa; - d->loc[UNW_ARM_R7] = DWARF_REG_LOC (d, UNW_ARM_R7); - d->loc[UNW_ARM_R13] = DWARF_REG_LOC (d, UNW_ARM_R13); - d->loc[UNW_ARM_R15] = DWARF_REG_LOC (d, UNW_ARM_R15); - c->frame_info = *f; - - if (likely(dwarf_put (d, d->loc[UNW_ARM_R7], r7) >= 0) - && likely(dwarf_put (d, d->loc[UNW_ARM_R13], sp) >= 0) - && likely(dwarf_put (d, d->loc[UNW_ARM_R15], pc) >= 0) - && likely((ret = unw_step (cursor)) >= 0)) - *f = c->frame_info; - - /* If unw_step() stopped voluntarily, remember that, even if it - otherwise could not determine anything useful. This avoids - failing trace if we hit frames without unwind info, which is - common for the outermost frame (CRT stuff) on many systems. - This avoids failing trace in very common circumstances; failing - to unw_step() loop wouldn't produce any better result. */ - if (ret == 0) - f->last_frame = -1; - - Debug (3, "frame va %x type %d last %d cfa %s+%d r7 @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n", - f->virtual_address, f->frame_type, f->last_frame, - f->cfa_reg_sp ? "sp" : "r7", f->cfa_reg_offset, - f->r7_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset); - - return f; -} - -/* Look up and if necessary fill in frame attributes for address PC - in CACHE using current CFA, R7 and SP values. Uses CURSOR to - perform any unwind steps necessary to fill the cache. Returns the - frame cache slot which describes RIP. */ -static unw_tdep_frame_t * -trace_lookup (unw_cursor_t *cursor, - unw_trace_cache_t *cache, - unw_word_t cfa, - unw_word_t pc, - unw_word_t r7, - unw_word_t sp) -{ - /* First look up for previously cached information using cache as - linear probing hash table with probe step of 1. Majority of - lookups should be completed within few steps, but it is very - important the hash table does not fill up, or performance falls - off the cliff. */ - uint32_t i, addr; - uint32_t cache_size = 1u << cache->log_size; - uint32_t slot = ((pc * 0x9e3779b9) >> 11) & (cache_size-1); - unw_tdep_frame_t *frame; - - for (i = 0; i < 16; ++i) - { - frame = &cache->frames[slot]; - addr = frame->virtual_address; - - /* Return if we found the address. */ - if (likely(addr == pc)) - { - Debug (4, "found address after %d steps\n", i); - return frame; - } - - /* If slot is empty, reuse it. */ - if (likely(! addr)) - break; - - /* Linear probe to next slot candidate, step = 1. */ - if (++slot >= cache_size) - slot -= cache_size; - } - - /* If we collided after 16 steps, or if the hash is more than half - full, force the hash to expand. Fill the selected slot, whether - it's free or collides. Note that hash expansion drops previous - contents; further lookups will refill the hash. */ - Debug (4, "updating slot %u after %d steps, replacing 0x%x\n", slot, i, addr); - if (unlikely(addr || cache->used >= cache_size / 2)) - { - if (unlikely(trace_cache_expand (cache) < 0)) - return NULL; - - cache_size = 1u << cache->log_size; - slot = ((pc * 0x9e3779b9) >> 11) & (cache_size-1); - frame = &cache->frames[slot]; - addr = frame->virtual_address; - } - - if (! addr) - ++cache->used; - - return trace_init_addr (frame, cursor, cfa, pc, r7, sp); -} - -/* Fast stack backtrace for ARM. - - This is used by backtrace() implementation to accelerate frequent - queries for current stack, without any desire to unwind. It fills - BUFFER with the call tree from CURSOR upwards for at most SIZE - stack levels. The first frame, backtrace itself, is omitted. When - called, SIZE should give the maximum number of entries that can be - stored into BUFFER. Uses an internal thread-specific cache to - accelerate queries. - - The caller should fall back to a unw_step() loop if this function - fails by returning -UNW_ESTOPUNWIND, meaning the routine hit a - stack frame that is too complex to be traced in the fast path. - - This function is tuned for clients which only need to walk the - stack to get the call tree as fast as possible but without any - other details, for example profilers sampling the stack thousands - to millions of times per second. The routine handles the most - common ARM ABI stack layouts: CFA is R7 or SP plus/minus - constant offset, return address is in LR, and R7, LR and SP are - either unchanged or saved on stack at constant offset from the CFA; - the signal return frame; and frames without unwind info provided - they are at the outermost (final) frame or can conservatively be - assumed to be frame-pointer based. - - Any other stack layout will cause the routine to give up. There - are only a handful of relatively rarely used functions which do - not have a stack in the standard form: vfork, longjmp, setcontext - and _dl_runtime_profile on common linux systems for example. - - On success BUFFER and *SIZE reflect the trace progress up to *SIZE - stack levels or the outermost frame, which ever is less. It may - stop short of outermost frame if unw_step() loop would also do so, - e.g. if there is no more unwind information; this is not reported - as an error. - - The function returns a negative value for errors, -UNW_ESTOPUNWIND - if tracing stopped because of an unusual frame unwind info. The - BUFFER and *SIZE reflect tracing progress up to the error frame. - - Callers of this function would normally look like this: - - unw_cursor_t cur; - unw_context_t ctx; - void addrs[128]; - int depth = 128; - int ret; - - unw_getcontext(&ctx); - unw_init_local(&cur, &ctx); - if ((ret = unw_tdep_trace(&cur, addrs, &depth)) < 0) - { - depth = 0; - unw_getcontext(&ctx); - unw_init_local(&cur, &ctx); - while ((ret = unw_step(&cur)) > 0 && depth < 128) - { - unw_word_t ip; - unw_get_reg(&cur, UNW_REG_IP, &ip); - addresses[depth++] = (void *) ip; - } - } -*/ -HIDDEN int -tdep_trace (unw_cursor_t *cursor, void **buffer, int *size) -{ - struct cursor *c = (struct cursor *) cursor; - struct dwarf_cursor *d = &c->dwarf; - unw_trace_cache_t *cache; - unw_word_t sp, pc, cfa, r7, lr; - int maxdepth = 0; - int depth = 0; - int ret; - - /* Check input parametres. */ - if (unlikely(! cursor || ! buffer || ! size || (maxdepth = *size) <= 0)) - return -UNW_EINVAL; - - Debug (1, "begin ip 0x%x cfa 0x%x\n", d->ip, d->cfa); - - /* Tell core dwarf routines to call back to us. */ - d->stash_frames = 1; - - /* Determine initial register values. These are direct access safe - because we know they come from the initial machine context. */ - pc = d->ip; - sp = cfa = d->cfa; - ACCESS_MEM_FAST(ret, 0, d, DWARF_GET_LOC(d->loc[UNW_ARM_R7]), r7); - assert(ret == 0); - lr = 0; - - /* Get frame cache. */ - if (unlikely(! (cache = trace_cache_get()))) - { - Debug (1, "returning %d, cannot get trace cache\n", -UNW_ENOMEM); - *size = 0; - d->stash_frames = 0; - return -UNW_ENOMEM; - } - - /* Trace the stack upwards, starting from current PC. Adjust - the PC address for previous/next instruction as the main - unwinding logic would also do. We undo this before calling - back into unw_step(). */ - while (depth < maxdepth) - { - pc -= d->use_prev_instr; - Debug (2, "depth %d cfa 0x%x pc 0x%x sp 0x%x r7 0x%x\n", - depth, cfa, pc, sp, r7); - - /* See if we have this address cached. If not, evaluate enough of - the dwarf unwind information to fill the cache line data, or to - decide this frame cannot be handled in fast trace mode. We - cache negative results too to prevent unnecessary dwarf parsing - for common failures. */ - unw_tdep_frame_t *f = trace_lookup (cursor, cache, cfa, pc, r7, sp); - - /* If we don't have information for this frame, give up. */ - if (unlikely(! f)) - { - ret = -UNW_ENOINFO; - break; - } - - Debug (3, "frame va %x type %d last %d cfa %s+%d r7 @ cfa%+d lr @ cfa%+d sp @ cfa%+d\n", - f->virtual_address, f->frame_type, f->last_frame, - f->cfa_reg_sp ? "sp" : "r7", f->cfa_reg_offset, - f->r7_cfa_offset, f->lr_cfa_offset, f->sp_cfa_offset); - - assert (f->virtual_address == pc); - - /* Stop if this was the last frame. In particular don't evaluate - new register values as it may not be safe - we don't normally - run with full validation on, and do not want to - and there's - enough bad unwind info floating around that we need to trust - what unw_step() previously said, in potentially bogus frames. */ - if (f->last_frame) - break; - - /* Evaluate CFA and registers for the next frame. */ - switch (f->frame_type) - { - case UNW_ARM_FRAME_GUESSED: - /* Fall thru to standard processing after forcing validation. */ - c->validate = 1; - - case UNW_ARM_FRAME_STANDARD: - /* Advance standard traceable frame. */ - cfa = (f->cfa_reg_sp ? sp : r7) + f->cfa_reg_offset; - if (likely(f->lr_cfa_offset != -1)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->lr_cfa_offset, pc); - else if (lr != 0) - { - /* Use the saved link register as the new pc. */ - pc = lr; - lr = 0; - } - if (likely(ret >= 0) && likely(f->r7_cfa_offset != -1)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->r7_cfa_offset, r7); - - /* Don't bother reading SP from DWARF, CFA becomes new SP. */ - sp = cfa; - - /* Next frame needs to back up for unwind info lookup. */ - d->use_prev_instr = 1; - break; - - case UNW_ARM_FRAME_SIGRETURN: - cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t. */ -#if defined(__linux__) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_PC_OFF, pc); - if (likely(ret >= 0)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_R7_OFF, r7); - if (likely(ret >= 0)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_SP_OFF, sp); - /* Save the link register here in case we end up in a function that - doesn't save the link register in the prologue, e.g. kill. */ - if (likely(ret >= 0)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + LINUX_SC_LR_OFF, lr); -#elif defined(__FreeBSD__) - printf("XXX\n"); -#endif - - /* Resume stack at signal restoration point. The stack is not - necessarily continuous here, especially with sigaltstack(). */ - cfa = sp; - - /* Next frame should not back up. */ - d->use_prev_instr = 0; - break; - - case UNW_ARM_FRAME_SYSCALL: - printf("XXX1\n"); - break; - - default: - /* We cannot trace through this frame, give up and tell the - caller we had to stop. Data collected so far may still be - useful to the caller, so let it know how far we got. */ - ret = -UNW_ESTOPUNWIND; - break; - } - - Debug (4, "new cfa 0x%x pc 0x%x sp 0x%x r7 0x%x\n", - cfa, pc, sp, r7); - - /* If we failed or ended up somewhere bogus, stop. */ - if (unlikely(ret < 0 || pc < 0x4000)) - break; - - /* Record this address in stack trace. We skipped the first address. */ - buffer[depth++] = (void *) (pc - d->use_prev_instr); - } - -#if UNW_DEBUG - Debug (1, "returning %d, depth %d\n", ret, depth); -#endif - *size = depth; - return ret; -} - diff --git a/contrib/libunwind/src/arm/Lapply_reg_state.c b/contrib/libunwind/src/arm/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/arm/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/arm/Lcreate_addr_space.c b/contrib/libunwind/src/arm/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901..00000000000 --- a/contrib/libunwind/src/arm/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/contrib/libunwind/src/arm/Lex_tables.c b/contrib/libunwind/src/arm/Lex_tables.c deleted file mode 100644 index 4a4f925c9c3..00000000000 --- a/contrib/libunwind/src/arm/Lex_tables.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gex_tables.c" -#endif diff --git a/contrib/libunwind/src/arm/Lget_proc_info.c b/contrib/libunwind/src/arm/Lget_proc_info.c deleted file mode 100644 index 69028b019fc..00000000000 --- a/contrib/libunwind/src/arm/Lget_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info.c" -#endif diff --git a/contrib/libunwind/src/arm/Lget_save_loc.c b/contrib/libunwind/src/arm/Lget_save_loc.c deleted file mode 100644 index 9ea048a9076..00000000000 --- a/contrib/libunwind/src/arm/Lget_save_loc.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_save_loc.c" -#endif diff --git a/contrib/libunwind/src/arm/Lglobal.c b/contrib/libunwind/src/arm/Lglobal.c deleted file mode 100644 index 6d7b489e14b..00000000000 --- a/contrib/libunwind/src/arm/Lglobal.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/contrib/libunwind/src/arm/Linit.c b/contrib/libunwind/src/arm/Linit.c deleted file mode 100644 index e9abfdd46a3..00000000000 --- a/contrib/libunwind/src/arm/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/contrib/libunwind/src/arm/Linit_local.c b/contrib/libunwind/src/arm/Linit_local.c deleted file mode 100644 index 68a1687e854..00000000000 --- a/contrib/libunwind/src/arm/Linit_local.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_local.c" -#endif diff --git a/contrib/libunwind/src/arm/Linit_remote.c b/contrib/libunwind/src/arm/Linit_remote.c deleted file mode 100644 index 58cb04ab7cd..00000000000 --- a/contrib/libunwind/src/arm/Linit_remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_remote.c" -#endif diff --git a/contrib/libunwind/src/arm/Lis_signal_frame.c b/contrib/libunwind/src/arm/Lis_signal_frame.c deleted file mode 100644 index b9a7c4f51ad..00000000000 --- a/contrib/libunwind/src/arm/Lis_signal_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gis_signal_frame.c" -#endif diff --git a/contrib/libunwind/src/arm/Los-freebsd.c b/contrib/libunwind/src/arm/Los-freebsd.c deleted file mode 100644 index a75a205df19..00000000000 --- a/contrib/libunwind/src/arm/Los-freebsd.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gos-freebsd.c" -#endif diff --git a/contrib/libunwind/src/arm/Los-linux.c b/contrib/libunwind/src/arm/Los-linux.c deleted file mode 100644 index 3cc18aabcc3..00000000000 --- a/contrib/libunwind/src/arm/Los-linux.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gos-linux.c" -#endif diff --git a/contrib/libunwind/src/arm/Los-other.c b/contrib/libunwind/src/arm/Los-other.c deleted file mode 100644 index a75a205df19..00000000000 --- a/contrib/libunwind/src/arm/Los-other.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gos-freebsd.c" -#endif diff --git a/contrib/libunwind/src/arm/Lreg_states_iterate.c b/contrib/libunwind/src/arm/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/arm/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/arm/Lregs.c b/contrib/libunwind/src/arm/Lregs.c deleted file mode 100644 index 2c9c75cd7d9..00000000000 --- a/contrib/libunwind/src/arm/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/contrib/libunwind/src/arm/Lresume.c b/contrib/libunwind/src/arm/Lresume.c deleted file mode 100644 index 41a8cf003de..00000000000 --- a/contrib/libunwind/src/arm/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/contrib/libunwind/src/arm/Lstash_frame.c b/contrib/libunwind/src/arm/Lstash_frame.c deleted file mode 100644 index 77587803d08..00000000000 --- a/contrib/libunwind/src/arm/Lstash_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstash_frame.c" -#endif diff --git a/contrib/libunwind/src/arm/Lstep.c b/contrib/libunwind/src/arm/Lstep.c deleted file mode 100644 index c1ac3c7547f..00000000000 --- a/contrib/libunwind/src/arm/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/contrib/libunwind/src/arm/Ltrace.c b/contrib/libunwind/src/arm/Ltrace.c deleted file mode 100644 index 24b7b3cfa62..00000000000 --- a/contrib/libunwind/src/arm/Ltrace.c +++ /dev/null @@ -1,6 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gtrace.c" -#endif - diff --git a/contrib/libunwind/src/arm/gen-offsets.c b/contrib/libunwind/src/arm/gen-offsets.c deleted file mode 100644 index 7d6bf2f1c57..00000000000 --- a/contrib/libunwind/src/arm/gen-offsets.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include -#include - -#define UC(N,X) \ - printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X)) - -#define SC(N,X) \ - printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X)) - -int -main (void) -{ - printf ( -"/* Linux-specific definitions: */\n\n" - -"/* Define various structure offsets to simplify cross-compilation. */\n\n" - -"/* Offsets for ARM Linux \"ucontext_t\": */\n\n"); - - UC ("FLAGS", uc_flags); - UC ("LINK", uc_link); - UC ("STACK", uc_stack); - UC ("MCONTEXT", uc_mcontext); - UC ("SIGMASK", uc_sigmask); - UC ("REGSPACE", uc_regspace); - - printf ("\n/* Offsets for ARM Linux \"struct sigcontext\": */\n\n"); - - SC ("TRAPNO", trap_no); - SC ("ERRORCODE", error_code); - SC ("OLDMASK", oldmask); - SC ("R0", arm_r0); - SC ("R1", arm_r1); - SC ("R2", arm_r2); - SC ("R3", arm_r3); - SC ("R4", arm_r4); - SC ("R5", arm_r5); - SC ("R6", arm_r6); - SC ("R7", arm_r7); - SC ("R8", arm_r8); - SC ("R9", arm_r9); - SC ("R10", arm_r10); - SC ("FP", arm_fp); - SC ("IP", arm_ip); - SC ("SP", arm_sp); - SC ("LR", arm_lr); - SC ("PC", arm_pc); - SC ("CPSR", arm_cpsr); - SC ("FAULTADDR", fault_address); - - return 0; -} diff --git a/contrib/libunwind/src/arm/getcontext.S b/contrib/libunwind/src/arm/getcontext.S deleted file mode 100644 index 7e18784477d..00000000000 --- a/contrib/libunwind/src/arm/getcontext.S +++ /dev/null @@ -1,63 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "offsets.h" - - .text - .arm - - .global _Uarm_getcontext - .type _Uarm_getcontext, %function - @ This is a stub version of getcontext() for ARM which only stores core - @ registers. It must be called in a special way, not as a regular - @ function -- see also the libunwind-arm.h:unw_tdep_getcontext macro. -_Uarm_getcontext: - stmfd sp!, {r0, r1} - @ store r0 -#if defined(__linux__) - str r0, [r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF] - add r0, r0, #LINUX_UC_MCONTEXT_OFF + LINUX_SC_R0_OFF -#elif defined(__FreeBSD__) - str r0, [r0, #FREEBSD_UC_MCONTEXT_OFF + FREEBSD_MC_R0_OFF] - add r0, r0, #FREEBSD_UC_MCONTEXT_OFF + FREEBSD_MC_R0_OFF -#else -#error Fix me -#endif - @ store r1 to r12 - stmib r0, {r1-r12} - @ reconstruct r13 at call site, then store - add r1, sp, #12 - str r1, [r0, #13 * 4] - @ retrieve r14 from call site, then store - ldr r1, [sp, #8] - str r1, [r0, #14 * 4] - @ point lr to instruction after call site's stack adjustment - add r1, lr, #4 - str r1, [r0, #15 * 4] - ldmfd sp!, {r0, r1} - bx lr -#if defined(__linux__) || defined(__FreeBSD__) - /* We do not need executable stack. */ - .section .note.GNU-stack,"",%progbits -#endif diff --git a/contrib/libunwind/src/arm/init.h b/contrib/libunwind/src/arm/init.h deleted file mode 100644 index 7d765ecf097..00000000000 --- a/contrib/libunwind/src/arm/init.h +++ /dev/null @@ -1,77 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static inline int -common_init (struct cursor *c, unsigned use_prev_instr) -{ - int ret, i; - - c->dwarf.loc[UNW_ARM_R0] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R0); - c->dwarf.loc[UNW_ARM_R1] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R1); - c->dwarf.loc[UNW_ARM_R2] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R2); - c->dwarf.loc[UNW_ARM_R3] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R3); - c->dwarf.loc[UNW_ARM_R4] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R4); - c->dwarf.loc[UNW_ARM_R5] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R5); - c->dwarf.loc[UNW_ARM_R6] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R6); - c->dwarf.loc[UNW_ARM_R7] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R7); - c->dwarf.loc[UNW_ARM_R8] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R8); - c->dwarf.loc[UNW_ARM_R9] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R9); - c->dwarf.loc[UNW_ARM_R10] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R10); - c->dwarf.loc[UNW_ARM_R11] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R11); - c->dwarf.loc[UNW_ARM_R12] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R12); - c->dwarf.loc[UNW_ARM_R13] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13); - c->dwarf.loc[UNW_ARM_R14] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R14); - c->dwarf.loc[UNW_ARM_R15] = DWARF_REG_LOC (&c->dwarf, UNW_ARM_R15); - for (i = UNW_ARM_R15 + 1; i < DWARF_NUM_PRESERVED_REGS; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_ARM_R15], &c->dwarf.ip); - if (ret < 0) - return ret; - - /* FIXME: correct for ARM? */ - ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_ARM_R13), - &c->dwarf.cfa); - if (ret < 0) - return ret; - - c->sigcontext_format = ARM_SCF_NONE; - c->sigcontext_addr = 0; - c->sigcontext_sp = 0; - c->sigcontext_pc = 0; - - /* FIXME: Initialisation for other registers. */ - - c->dwarf.args_size = 0; - c->dwarf.stash_frames = 0; - c->dwarf.use_prev_instr = use_prev_instr; - c->dwarf.pi_valid = 0; - c->dwarf.pi_is_dynamic = 0; - c->dwarf.hint = 0; - c->dwarf.prev_rs = 0; - - return 0; -} diff --git a/contrib/libunwind/src/arm/is_fpreg.c b/contrib/libunwind/src/arm/is_fpreg.c deleted file mode 100644 index 3b36a03d10f..00000000000 --- a/contrib/libunwind/src/arm/is_fpreg.c +++ /dev/null @@ -1,39 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -/* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful - on ARM. Count all the FP or coprocessor registers we know about for now. */ - -PROTECTED int -unw_is_fpreg (int regnum) -{ - return ((regnum >= UNW_ARM_S0 && regnum <= UNW_ARM_S31) - || (regnum >= UNW_ARM_F0 && regnum <= UNW_ARM_F7) - || (regnum >= UNW_ARM_wCGR0 && regnum <= UNW_ARM_wCGR7) - || (regnum >= UNW_ARM_wR0 && regnum <= UNW_ARM_wR15) - || (regnum >= UNW_ARM_wC0 && regnum <= UNW_ARM_wC7) - || (regnum >= UNW_ARM_D0 && regnum <= UNW_ARM_D31)); -} diff --git a/contrib/libunwind/src/arm/offsets.h b/contrib/libunwind/src/arm/offsets.h deleted file mode 100644 index 621701106c4..00000000000 --- a/contrib/libunwind/src/arm/offsets.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Linux-specific definitions: */ - -/* Define various structure offsets to simplify cross-compilation. */ - -/* Offsets for ARM Linux "ucontext_t": */ - -#define LINUX_UC_FLAGS_OFF 0x00 -#define LINUX_UC_LINK_OFF 0x04 -#define LINUX_UC_STACK_OFF 0x08 -#define LINUX_UC_MCONTEXT_OFF 0x14 -#define LINUX_UC_SIGMASK_OFF 0x68 -#define LINUX_UC_REGSPACE_OFF 0xE8 - -/* Offsets for ARM Linux "struct sigcontext": */ - -#define LINUX_SC_TRAPNO_OFF 0x00 -#define LINUX_SC_ERRORCODE_OFF 0x04 -#define LINUX_SC_OLDMASK_OFF 0x08 -#define LINUX_SC_R0_OFF 0x0C -#define LINUX_SC_R1_OFF 0x10 -#define LINUX_SC_R2_OFF 0x14 -#define LINUX_SC_R3_OFF 0x18 -#define LINUX_SC_R4_OFF 0x1C -#define LINUX_SC_R5_OFF 0x20 -#define LINUX_SC_R6_OFF 0x24 -#define LINUX_SC_R7_OFF 0x28 -#define LINUX_SC_R8_OFF 0x2C -#define LINUX_SC_R9_OFF 0x30 -#define LINUX_SC_R10_OFF 0x34 -#define LINUX_SC_FP_OFF 0x38 -#define LINUX_SC_IP_OFF 0x3C -#define LINUX_SC_SP_OFF 0x40 -#define LINUX_SC_LR_OFF 0x44 -#define LINUX_SC_PC_OFF 0x48 -#define LINUX_SC_CPSR_OFF 0x4C -#define LINUX_SC_FAULTADDR_OFF 0x50 - -/* FreeBSD-specific definitions: */ - -#define FREEBSD_SC_UCONTEXT_OFF 0x40 -#define FREEBSD_UC_MCONTEXT_OFF 0x10 -#define FREEBSD_MC_R0_OFF 0 diff --git a/contrib/libunwind/src/arm/regname.c b/contrib/libunwind/src/arm/regname.c deleted file mode 100644 index 474337a5689..00000000000 --- a/contrib/libunwind/src/arm/regname.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "unwind_i.h" - -static const char *regname[] = - { - /* 0. */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - /* 8. */ - "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc", - /* 16. Obsolete FPA names. */ - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", - /* 24. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 32. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 40. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 48. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 56. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 64. */ - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", - /* 72. */ - "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", - /* 80. */ - "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", - /* 88. */ - "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", - /* 96. */ - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", - /* 104. */ - "wCGR0", "wCGR1", "wCGR2", "wCGR3", "wCGR4", "wCGR5", "wCGR6", "wCGR7", - /* 112. */ - "wR0", "wR1", "wR2", "wR3", "wR4", "wR5", "wR6", "wR7", - /* 128. */ - "spsr", "spsr_fiq", "spsr_irq", "spsr_abt", "spsr_und", "spsr_svc", 0, 0, - /* 136. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 144. */ - "r8_usr", "r9_usr", "r10_usr", "r11_usr", "r12_usr", "r13_usr", "r14_usr", - /* 151. */ - "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "r14_fiq", - /* 158. */ - "r13_irq", "r14_irq", - /* 160. */ - "r13_abt", "r14_abt", - /* 162. */ - "r13_und", "r14_und", - /* 164. */ - "r13_svc", "r14_svc", 0, 0, - /* 168. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 176. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 184. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 192. */ - "wC0", "wC1", "wC2", "wC3", "wC4", "wC5", "wC6", "wC7", - /* 200. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 208. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 216. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 224. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 232. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 240. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 248. */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 256. */ - "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", - /* 264. */ - "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", - /* 272. */ - "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", - /* 280. */ - "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", - }; - -PROTECTED const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) - return regname[reg]; - else - return "???"; -} diff --git a/contrib/libunwind/src/arm/siglongjmp.S b/contrib/libunwind/src/arm/siglongjmp.S deleted file mode 100644 index 4df07366831..00000000000 --- a/contrib/libunwind/src/arm/siglongjmp.S +++ /dev/null @@ -1,12 +0,0 @@ - /* Dummy implementation for now. */ - - .globl _UI_siglongjmp_cont - .globl _UI_longjmp_cont - -_UI_siglongjmp_cont: -_UI_longjmp_cont: - bx lr -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",%progbits -#endif diff --git a/contrib/libunwind/src/arm/unwind_i.h b/contrib/libunwind/src/arm/unwind_i.h deleted file mode 100644 index 4dabf217c5e..00000000000 --- a/contrib/libunwind/src/arm/unwind_i.h +++ /dev/null @@ -1,59 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include - -#include - -#include "libunwind_i.h" - -/* DWARF column numbers for ARM: */ -#define R7 7 -#define SP 13 -#define LR 14 -#define PC 15 - -#define arm_lock UNW_OBJ(lock) -#define arm_local_resume UNW_OBJ(local_resume) -#define arm_local_addr_space_init UNW_OBJ(local_addr_space_init) - -extern void arm_local_addr_space_init (void); -extern int arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, - void *arg); -/* By-pass calls to access_mem() when known to be safe. */ -#ifdef UNW_LOCAL_ONLY -# undef ACCESS_MEM_FAST -# define ACCESS_MEM_FAST(ret,validate,cur,addr,to) \ - do { \ - if (unlikely(validate)) \ - (ret) = dwarf_get ((cur), DWARF_MEM_LOC ((cur), (addr)), &(to)); \ - else \ - (ret) = 0, (to) = *(unw_word_t *)(addr); \ - } while (0) -#endif - -#endif /* unwind_i_h */ diff --git a/contrib/libunwind/src/coredump/README b/contrib/libunwind/src/coredump/README deleted file mode 100644 index 204493c93e9..00000000000 --- a/contrib/libunwind/src/coredump/README +++ /dev/null @@ -1,8 +0,0 @@ -This code is based on "unwinding via ptrace" code from ptrace/ -directory. - -Files with names starting with _UCD_ are substantially changed -from their ptrace/_UPT_... progenitors. - -Files which still have _UPT_... names are either verbiatim copies -from ptrace/, or unimplemented stubs. diff --git a/contrib/libunwind/src/coredump/_UCD_access_mem.c b/contrib/libunwind/src/coredump/_UCD_access_mem.c deleted file mode 100644 index 1fdbd128ffc..00000000000 --- a/contrib/libunwind/src/coredump/_UCD_access_mem.c +++ /dev/null @@ -1,98 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UCD_lib.h" -#include "_UCD_internal.h" - -int -_UCD_access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *val, - int write, void *arg) -{ - if (write) - { - Debug(0, "write is not supported\n"); - return -UNW_EINVAL; - } - - struct UCD_info *ui = arg; - - unw_word_t addr_last = addr + sizeof(*val)-1; - coredump_phdr_t *phdr; - unsigned i; - for (i = 0; i < ui->phdrs_count; i++) - { - phdr = &ui->phdrs[i]; - if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + phdr->p_memsz) - { - goto found; - } - } - Debug(1, "addr 0x%llx is unmapped\n", (unsigned long long)addr); - return -UNW_EINVAL; - - found: ; - - const char *filename UNUSED; - off_t fileofs; - int fd; - if (addr_last >= phdr->p_vaddr + phdr->p_filesz) - { - /* This part of mapped address space is not present in coredump file */ - /* Do we have it in the backup file? */ - if (phdr->backing_fd < 0) - { - Debug(1, "access to not-present data in phdr[%d]: addr:0x%llx\n", - i, (unsigned long long)addr - ); - return -UNW_EINVAL; - } - filename = phdr->backing_filename; - fileofs = addr - phdr->p_vaddr; - fd = phdr->backing_fd; - goto read; - } - - filename = ui->coredump_filename; - fileofs = phdr->p_offset + (addr - phdr->p_vaddr); - fd = ui->coredump_fd; - read: - if (lseek(fd, fileofs, SEEK_SET) != fileofs) - goto read_error; - if (read(fd, val, sizeof(*val)) != sizeof(*val)) - goto read_error; - - Debug(1, "0x%llx <- [addr:0x%llx fileofs:0x%llx]\n", - (unsigned long long)(*val), - (unsigned long long)addr, - (unsigned long long)fileofs - ); - return 0; - - read_error: - Debug(1, "access out of file: addr:0x%llx fileofs:%llx file:'%s'\n", - (unsigned long long)addr, - (unsigned long long)fileofs, - filename - ); - return -UNW_EINVAL; -} diff --git a/contrib/libunwind/src/coredump/_UCD_access_reg_freebsd.c b/contrib/libunwind/src/coredump/_UCD_access_reg_freebsd.c deleted file mode 100644 index 0e3a83bdc6c..00000000000 --- a/contrib/libunwind/src/coredump/_UCD_access_reg_freebsd.c +++ /dev/null @@ -1,137 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UCD_lib.h" - -#include "_UCD_internal.h" - -int -_UCD_access_reg (unw_addr_space_t as, - unw_regnum_t regnum, unw_word_t *valp, - int write, void *arg) -{ - if (write) - { - Debug(0, "write is not supported\n"); - return -UNW_EINVAL; - } - - struct UCD_info *ui = arg; - -#if defined(UNW_TARGET_X86) - switch (regnum) { - case UNW_X86_EAX: - *valp = ui->prstatus->pr_reg.r_eax; - break; - case UNW_X86_EDX: - *valp = ui->prstatus->pr_reg.r_edx; - break; - case UNW_X86_ECX: - *valp = ui->prstatus->pr_reg.r_ecx; - break; - case UNW_X86_EBX: - *valp = ui->prstatus->pr_reg.r_ebx; - break; - case UNW_X86_ESI: - *valp = ui->prstatus->pr_reg.r_esi; - break; - case UNW_X86_EDI: - *valp = ui->prstatus->pr_reg.r_edi; - break; - case UNW_X86_EBP: - *valp = ui->prstatus->pr_reg.r_ebp; - break; - case UNW_X86_ESP: - *valp = ui->prstatus->pr_reg.r_esp; - break; - case UNW_X86_EIP: - *valp = ui->prstatus->pr_reg.r_eip; - break; - case UNW_X86_EFLAGS: - *valp = ui->prstatus->pr_reg.r_eflags; - break; - case UNW_X86_TRAPNO: - *valp = ui->prstatus->pr_reg.r_trapno; - break; - default: - Debug(0, "bad regnum:%d\n", regnum); - return -UNW_EINVAL; - } -#elif defined(UNW_TARGET_X86_64) - switch (regnum) { - case UNW_X86_64_RAX: - *valp = ui->prstatus->pr_reg.r_rax; - break; - case UNW_X86_64_RDX: - *valp = ui->prstatus->pr_reg.r_rdx; - break; - case UNW_X86_64_RCX: - *valp = ui->prstatus->pr_reg.r_rcx; - break; - case UNW_X86_64_RBX: - *valp = ui->prstatus->pr_reg.r_rbx; - break; - case UNW_X86_64_RSI: - *valp = ui->prstatus->pr_reg.r_rsi; - break; - case UNW_X86_64_RDI: - *valp = ui->prstatus->pr_reg.r_rdi; - break; - case UNW_X86_64_RBP: - *valp = ui->prstatus->pr_reg.r_rbp; - break; - case UNW_X86_64_RSP: - *valp = ui->prstatus->pr_reg.r_rsp; - break; - case UNW_X86_64_RIP: - *valp = ui->prstatus->pr_reg.r_rip; - break; - default: - Debug(0, "bad regnum:%d\n", regnum); - return -UNW_EINVAL; - } -#elif defined(UNW_TARGET_ARM) - if (regnum >= UNW_ARM_R0 && regnum <= UNW_ARM_R12) { - *valp = ui->prstatus->pr_reg.r[regnum]; - } else { - switch (regnum) { - case UNW_ARM_R13: - *valp = ui->prstatus->pr_reg.r_sp; - break; - case UNW_ARM_R14: - *valp = ui->prstatus->pr_reg.r_lr; - break; - case UNW_ARM_R15: - *valp = ui->prstatus->pr_reg.r_pc; - break; - default: - Debug(0, "bad regnum:%d\n", regnum); - return -UNW_EINVAL; - } - } -#else -#error Port me -#endif - - return 0; -} diff --git a/contrib/libunwind/src/coredump/_UCD_access_reg_linux.c b/contrib/libunwind/src/coredump/_UCD_access_reg_linux.c deleted file mode 100644 index 208d8d27b65..00000000000 --- a/contrib/libunwind/src/coredump/_UCD_access_reg_linux.c +++ /dev/null @@ -1,146 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UCD_lib.h" - -#include "_UCD_internal.h" - -int -_UCD_access_reg (unw_addr_space_t as, - unw_regnum_t regnum, unw_word_t *valp, - int write, void *arg) -{ - struct UCD_info *ui = arg; - - if (write) - { - Debug(0, "write is not supported\n"); - return -UNW_EINVAL; - } - - if (regnum < 0) - goto badreg; - -#if defined(UNW_TARGET_AARCH64) - if (regnum >= UNW_AARCH64_FPCR) - goto badreg; -#elif defined(UNW_TARGET_ARM) - if (regnum >= 16) - goto badreg; -#elif defined(UNW_TARGET_SH) - if (regnum > UNW_SH_PR) - goto badreg; -#elif defined(UNW_TARGET_TILEGX) - if (regnum > UNW_TILEGX_CFA) - goto badreg; -#else -#if defined(UNW_TARGET_MIPS) - static const uint8_t remap_regs[] = - { - [UNW_MIPS_R0] = EF_REG0, - [UNW_MIPS_R1] = EF_REG1, - [UNW_MIPS_R2] = EF_REG2, - [UNW_MIPS_R3] = EF_REG3, - [UNW_MIPS_R4] = EF_REG4, - [UNW_MIPS_R5] = EF_REG5, - [UNW_MIPS_R6] = EF_REG6, - [UNW_MIPS_R7] = EF_REG7, - [UNW_MIPS_R8] = EF_REG8, - [UNW_MIPS_R9] = EF_REG9, - [UNW_MIPS_R10] = EF_REG10, - [UNW_MIPS_R11] = EF_REG11, - [UNW_MIPS_R12] = EF_REG12, - [UNW_MIPS_R13] = EF_REG13, - [UNW_MIPS_R14] = EF_REG14, - [UNW_MIPS_R15] = EF_REG15, - [UNW_MIPS_R16] = EF_REG16, - [UNW_MIPS_R17] = EF_REG17, - [UNW_MIPS_R18] = EF_REG18, - [UNW_MIPS_R19] = EF_REG19, - [UNW_MIPS_R20] = EF_REG20, - [UNW_MIPS_R21] = EF_REG21, - [UNW_MIPS_R22] = EF_REG22, - [UNW_MIPS_R23] = EF_REG23, - [UNW_MIPS_R24] = EF_REG24, - [UNW_MIPS_R25] = EF_REG25, - [UNW_MIPS_R28] = EF_REG28, - [UNW_MIPS_R29] = EF_REG29, - [UNW_MIPS_R30] = EF_REG30, - [UNW_MIPS_R31] = EF_REG31, - [UNW_MIPS_PC] = EF_CP0_EPC, - }; -#elif defined(UNW_TARGET_X86) - static const uint8_t remap_regs[] = - { - /* names from libunwind-x86.h */ - [UNW_X86_EAX] = offsetof(struct user_regs_struct, eax) / sizeof(long), - [UNW_X86_EDX] = offsetof(struct user_regs_struct, edx) / sizeof(long), - [UNW_X86_ECX] = offsetof(struct user_regs_struct, ecx) / sizeof(long), - [UNW_X86_EBX] = offsetof(struct user_regs_struct, ebx) / sizeof(long), - [UNW_X86_ESI] = offsetof(struct user_regs_struct, esi) / sizeof(long), - [UNW_X86_EDI] = offsetof(struct user_regs_struct, edi) / sizeof(long), - [UNW_X86_EBP] = offsetof(struct user_regs_struct, ebp) / sizeof(long), - [UNW_X86_ESP] = offsetof(struct user_regs_struct, esp) / sizeof(long), - [UNW_X86_EIP] = offsetof(struct user_regs_struct, eip) / sizeof(long), - [UNW_X86_EFLAGS] = offsetof(struct user_regs_struct, eflags) / sizeof(long), - [UNW_X86_TRAPNO] = offsetof(struct user_regs_struct, orig_eax) / sizeof(long), - }; -#elif defined(UNW_TARGET_X86_64) - static const int8_t remap_regs[] = - { - [UNW_X86_64_RAX] = offsetof(struct user_regs_struct, rax) / sizeof(long), - [UNW_X86_64_RDX] = offsetof(struct user_regs_struct, rdx) / sizeof(long), - [UNW_X86_64_RCX] = offsetof(struct user_regs_struct, rcx) / sizeof(long), - [UNW_X86_64_RBX] = offsetof(struct user_regs_struct, rbx) / sizeof(long), - [UNW_X86_64_RSI] = offsetof(struct user_regs_struct, rsi) / sizeof(long), - [UNW_X86_64_RDI] = offsetof(struct user_regs_struct, rdi) / sizeof(long), - [UNW_X86_64_RBP] = offsetof(struct user_regs_struct, rbp) / sizeof(long), - [UNW_X86_64_RSP] = offsetof(struct user_regs_struct, rsp) / sizeof(long), - [UNW_X86_64_RIP] = offsetof(struct user_regs_struct, rip) / sizeof(long), - }; -#else -#error Port me -#endif - - if (regnum >= (unw_regnum_t)ARRAY_SIZE(remap_regs)) - goto badreg; - - regnum = remap_regs[regnum]; -#endif - - /* pr_reg is a long[] array, but it contains struct user_regs_struct's - * image. - */ - Debug(1, "pr_reg[%d]:%ld (0x%lx)\n", regnum, - (long)ui->prstatus->pr_reg[regnum], - (long)ui->prstatus->pr_reg[regnum] - ); - *valp = ui->prstatus->pr_reg[regnum]; - - return 0; - -badreg: - Debug(0, "bad regnum:%d\n", regnum); - return -UNW_EINVAL; -} diff --git a/contrib/libunwind/src/coredump/_UCD_accessors.c b/contrib/libunwind/src/coredump/_UCD_accessors.c deleted file mode 100644 index f0811803195..00000000000 --- a/contrib/libunwind/src/coredump/_UCD_accessors.c +++ /dev/null @@ -1,36 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UCD_internal.h" - -PROTECTED unw_accessors_t _UCD_accessors = - { - .find_proc_info = _UCD_find_proc_info, - .put_unwind_info = _UCD_put_unwind_info, - .get_dyn_info_list_addr = _UCD_get_dyn_info_list_addr, - .access_mem = _UCD_access_mem, - .access_reg = _UCD_access_reg, - .access_fpreg = _UCD_access_fpreg, - .resume = _UCD_resume, - .get_proc_name = _UCD_get_proc_name - }; diff --git a/contrib/libunwind/src/coredump/_UCD_create.c b/contrib/libunwind/src/coredump/_UCD_create.c deleted file mode 100644 index 62f6ee05c79..00000000000 --- a/contrib/libunwind/src/coredump/_UCD_create.c +++ /dev/null @@ -1,417 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -/* Endian detection */ -#include -#if defined(HAVE_BYTESWAP_H) -#include -#endif -#if defined(HAVE_ENDIAN_H) -# include -#elif defined(HAVE_SYS_ENDIAN_H) -# include -#endif -#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN -# define WE_ARE_BIG_ENDIAN 1 -# define WE_ARE_LITTLE_ENDIAN 0 -#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN -# define WE_ARE_BIG_ENDIAN 0 -# define WE_ARE_LITTLE_ENDIAN 1 -#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN -# define WE_ARE_BIG_ENDIAN 1 -# define WE_ARE_LITTLE_ENDIAN 0 -#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN -# define WE_ARE_BIG_ENDIAN 0 -# define WE_ARE_LITTLE_ENDIAN 1 -#elif defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN -# define WE_ARE_BIG_ENDIAN 1 -# define WE_ARE_LITTLE_ENDIAN 0 -#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN -# define WE_ARE_BIG_ENDIAN 0 -# define WE_ARE_LITTLE_ENDIAN 1 -#elif defined(__386__) -# define WE_ARE_BIG_ENDIAN 0 -# define WE_ARE_LITTLE_ENDIAN 1 -#else -# error "Can't determine endianness" -#endif - -#include -#include /* struct elf_prstatus */ - -#include "_UCD_lib.h" -#include "_UCD_internal.h" - -#define NOTE_DATA(_hdr) STRUCT_MEMBER_P((_hdr), sizeof (Elf32_Nhdr) + UNW_ALIGN((_hdr)->n_namesz, 4)) -#define NOTE_SIZE(_hdr) (sizeof (Elf32_Nhdr) + UNW_ALIGN((_hdr)->n_namesz, 4) + UNW_ALIGN((_hdr)->n_descsz, 4)) -#define NOTE_NEXT(_hdr) STRUCT_MEMBER_P((_hdr), NOTE_SIZE(_hdr)) -#define NOTE_FITS_IN(_hdr, _size) ((_size) >= sizeof (Elf32_Nhdr) && (_size) >= NOTE_SIZE (_hdr)) -#define NOTE_FITS(_hdr, _end) NOTE_FITS_IN((_hdr), (unsigned long)((char *)(_end) - (char *)(_hdr))) - -struct UCD_info * -_UCD_create(const char *filename) -{ - union - { - Elf32_Ehdr h32; - Elf64_Ehdr h64; - } elf_header; -#define elf_header32 elf_header.h32 -#define elf_header64 elf_header.h64 - bool _64bits; - - struct UCD_info *ui = memset(malloc(sizeof(*ui)), 0, sizeof(*ui)); - ui->edi.di_cache.format = -1; - ui->edi.di_debug.format = -1; -#if UNW_TARGET_IA64 - ui->edi.ktab.format = -1; -#endif - - int fd = ui->coredump_fd = open(filename, O_RDONLY); - if (fd < 0) - goto err; - ui->coredump_filename = strdup(filename); - - /* No sane ELF32 file is going to be smaller then ELF64 _header_, - * so let's just read 64-bit sized one. - */ - if (read(fd, &elf_header64, sizeof(elf_header64)) != sizeof(elf_header64)) - { - Debug(0, "'%s' is not an ELF file\n", filename); - goto err; - } - - if (memcmp(&elf_header32, ELFMAG, SELFMAG) != 0) - { - Debug(0, "'%s' is not an ELF file\n", filename); - goto err; - } - - if (elf_header32.e_ident[EI_CLASS] != ELFCLASS32 - && elf_header32.e_ident[EI_CLASS] != ELFCLASS64) - { - Debug(0, "'%s' is not a 32/64 bit ELF file\n", filename); - goto err; - } - - if (WE_ARE_LITTLE_ENDIAN != (elf_header32.e_ident[EI_DATA] == ELFDATA2LSB)) - { - Debug(0, "'%s' is endian-incompatible\n", filename); - goto err; - } - - _64bits = (elf_header32.e_ident[EI_CLASS] == ELFCLASS64); - if (_64bits && sizeof(elf_header64.e_entry) > sizeof(off_t)) - { - Debug(0, "Can't process '%s': 64-bit file " - "while only %ld bits are supported", - filename, 8L * sizeof(off_t)); - goto err; - } - - /* paranoia check */ - if (_64bits - ? 0 /* todo: (elf_header64.e_ehsize != NN || elf_header64.e_phentsize != NN) */ - : (elf_header32.e_ehsize != 52 || elf_header32.e_phentsize != 32) - ) - { - Debug(0, "'%s' has wrong e_ehsize or e_phentsize\n", filename); - goto err; - } - - off_t ofs = (_64bits ? elf_header64.e_phoff : elf_header32.e_phoff); - if (lseek(fd, ofs, SEEK_SET) != ofs) - { - Debug(0, "Can't read phdrs from '%s'\n", filename); - goto err; - } - unsigned size = ui->phdrs_count = (_64bits ? elf_header64.e_phnum : elf_header32.e_phnum); - coredump_phdr_t *phdrs = ui->phdrs = memset(malloc(size * sizeof(phdrs[0])), 0, size * sizeof(phdrs[0])); - if (_64bits) - { - coredump_phdr_t *cur = phdrs; - unsigned i = 0; - while (i < size) - { - Elf64_Phdr hdr64; - if (read(fd, &hdr64, sizeof(hdr64)) != sizeof(hdr64)) - { - Debug(0, "Can't read phdrs from '%s'\n", filename); - goto err; - } - cur->p_type = hdr64.p_type ; - cur->p_flags = hdr64.p_flags ; - cur->p_offset = hdr64.p_offset; - cur->p_vaddr = hdr64.p_vaddr ; - /*cur->p_paddr = hdr32.p_paddr ; always 0 */ -//TODO: check that and abort if it isn't? - cur->p_filesz = hdr64.p_filesz; - cur->p_memsz = hdr64.p_memsz ; - cur->p_align = hdr64.p_align ; - /* cur->backing_filename = NULL; - done by memset */ - cur->backing_fd = -1; - cur->backing_filesize = hdr64.p_filesz; - i++; - cur++; - } - } else { - coredump_phdr_t *cur = phdrs; - unsigned i = 0; - while (i < size) - { - Elf32_Phdr hdr32; - if (read(fd, &hdr32, sizeof(hdr32)) != sizeof(hdr32)) - { - Debug(0, "Can't read phdrs from '%s'\n", filename); - goto err; - } - cur->p_type = hdr32.p_type ; - cur->p_flags = hdr32.p_flags ; - cur->p_offset = hdr32.p_offset; - cur->p_vaddr = hdr32.p_vaddr ; - /*cur->p_paddr = hdr32.p_paddr ; always 0 */ - cur->p_filesz = hdr32.p_filesz; - cur->p_memsz = hdr32.p_memsz ; - cur->p_align = hdr32.p_align ; - /* cur->backing_filename = NULL; - done by memset */ - cur->backing_fd = -1; - cur->backing_filesize = hdr32.p_memsz; - i++; - cur++; - } - } - - unsigned i = 0; - coredump_phdr_t *cur = phdrs; - while (i < size) - { - Debug(2, "phdr[%03d]: type:%d", i, cur->p_type); - if (cur->p_type == PT_NOTE) - { - Elf32_Nhdr *note_hdr, *note_end; - unsigned n_threads; - - ui->note_phdr = malloc(cur->p_filesz); - if (lseek(fd, cur->p_offset, SEEK_SET) != (off_t)cur->p_offset - || (uoff_t)read(fd, ui->note_phdr, cur->p_filesz) != cur->p_filesz) - { - Debug(0, "Can't read PT_NOTE from '%s'\n", filename); - goto err; - } - - note_end = STRUCT_MEMBER_P (ui->note_phdr, cur->p_filesz); - - /* Count number of threads */ - n_threads = 0; - note_hdr = (Elf32_Nhdr *)ui->note_phdr; - while (NOTE_FITS (note_hdr, note_end)) - { - if (note_hdr->n_type == NT_PRSTATUS) - n_threads++; - - note_hdr = NOTE_NEXT (note_hdr); - } - - ui->n_threads = n_threads; - ui->threads = malloc(sizeof (void *) * n_threads); - - n_threads = 0; - note_hdr = (Elf32_Nhdr *)ui->note_phdr; - while (NOTE_FITS (note_hdr, note_end)) - { - if (note_hdr->n_type == NT_PRSTATUS) - ui->threads[n_threads++] = NOTE_DATA (note_hdr); - - note_hdr = NOTE_NEXT (note_hdr); - } - } - if (cur->p_type == PT_LOAD) - { - Debug(2, " ofs:%08llx va:%08llx filesize:%08llx memsize:%08llx flg:%x", - (unsigned long long) cur->p_offset, - (unsigned long long) cur->p_vaddr, - (unsigned long long) cur->p_filesz, - (unsigned long long) cur->p_memsz, - cur->p_flags - ); - if (cur->p_filesz < cur->p_memsz) - Debug(2, " partial"); - if (cur->p_flags & PF_X) - Debug(2, " executable"); - } - Debug(2, "\n"); - i++; - cur++; - } - - if (ui->n_threads == 0) - { - Debug(0, "No NT_PRSTATUS note found in '%s'\n", filename); - goto err; - } - - ui->prstatus = ui->threads[0]; - - return ui; - - err: - _UCD_destroy(ui); - return NULL; -} - -int _UCD_get_num_threads(struct UCD_info *ui) -{ - return ui->n_threads; -} - -void _UCD_select_thread(struct UCD_info *ui, int n) -{ - if (n >= 0 && n < ui->n_threads) - ui->prstatus = ui->threads[n]; -} - -pid_t _UCD_get_pid(struct UCD_info *ui) -{ - return ui->prstatus->pr_pid; -} - -int _UCD_get_cursig(struct UCD_info *ui) -{ - return ui->prstatus->pr_cursig; -} - -int _UCD_add_backing_file_at_segment(struct UCD_info *ui, int phdr_no, const char *filename) -{ - if ((unsigned)phdr_no >= ui->phdrs_count) - { - Debug(0, "There is no segment %d in this coredump\n", phdr_no); - return -1; - } - - struct coredump_phdr *phdr = &ui->phdrs[phdr_no]; - if (phdr->backing_filename) - { - Debug(0, "Backing file already added to segment %d\n", phdr_no); - return -1; - } - - int fd = open(filename, O_RDONLY); - if (fd < 0) - { - Debug(0, "Can't open '%s'\n", filename); - return -1; - } - - phdr->backing_fd = fd; - phdr->backing_filename = strdup(filename); - - struct stat statbuf; - if (fstat(fd, &statbuf) != 0) - { - Debug(0, "Can't stat '%s'\n", filename); - goto err; - } - phdr->backing_filesize = (uoff_t)statbuf.st_size; - - if (phdr->p_flags != (PF_X | PF_R)) - Debug(1, "Note: phdr[%u] is not r-x: flags are 0x%x\n", phdr_no, phdr->p_flags); - - if (phdr->backing_filesize > phdr->p_memsz) - { - /* This is expected */ - Debug(2, "Note: phdr[%u] is %lld bytes, file is larger: %lld bytes\n", - phdr_no, - (unsigned long long)phdr->p_memsz, - (unsigned long long)phdr->backing_filesize - ); - } -//TODO: else loudly complain? Maybe even fail? - - if (phdr->p_filesz != 0) - { -//TODO: loop and compare in smaller blocks - char *core_buf = malloc(phdr->p_filesz); - char *file_buf = malloc(phdr->p_filesz); - if (lseek(ui->coredump_fd, phdr->p_offset, SEEK_SET) != (off_t)phdr->p_offset - || (uoff_t)read(ui->coredump_fd, core_buf, phdr->p_filesz) != phdr->p_filesz - ) - { - Debug(0, "Error reading from coredump file\n"); - err_read: - free(core_buf); - free(file_buf); - goto err; - } - if ((uoff_t)read(fd, file_buf, phdr->p_filesz) != phdr->p_filesz) - { - Debug(0, "Error reading from '%s'\n", filename); - goto err_read; - } - int r = memcmp(core_buf, file_buf, phdr->p_filesz); - free(core_buf); - free(file_buf); - if (r != 0) - { - Debug(1, "Note: phdr[%u] first %lld bytes in core dump and in file do not match\n", - phdr_no, (unsigned long long)phdr->p_filesz - ); - } else { - Debug(1, "Note: phdr[%u] first %lld bytes in core dump and in file match\n", - phdr_no, (unsigned long long)phdr->p_filesz - ); - } - } - - /* Success */ - return 0; - - err: - if (phdr->backing_fd >= 0) - { - close(phdr->backing_fd); - phdr->backing_fd = -1; - } - free(phdr->backing_filename); - phdr->backing_filename = NULL; - return -1; -} - -int _UCD_add_backing_file_at_vaddr(struct UCD_info *ui, - unsigned long vaddr, - const char *filename) -{ - unsigned i; - for (i = 0; i < ui->phdrs_count; i++) - { - struct coredump_phdr *phdr = &ui->phdrs[i]; - if (phdr->p_vaddr != vaddr) - continue; - /* It seems to match. Add it. */ - return _UCD_add_backing_file_at_segment(ui, i, filename); - } - return -1; -} diff --git a/contrib/libunwind/src/coredump/_UCD_destroy.c b/contrib/libunwind/src/coredump/_UCD_destroy.c deleted file mode 100644 index ddc36ec8986..00000000000 --- a/contrib/libunwind/src/coredump/_UCD_destroy.c +++ /dev/null @@ -1,52 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UCD_internal.h" - -void -_UCD_destroy (struct UCD_info *ui) -{ - if (!ui) - return; - - if (ui->coredump_fd >= 0) - close(ui->coredump_fd); - free(ui->coredump_filename); - - invalidate_edi (&ui->edi); - - unsigned i; - for (i = 0; i < ui->phdrs_count; i++) - { - struct coredump_phdr *phdr = &ui->phdrs[i]; - free(phdr->backing_filename); - if (phdr->backing_fd >= 0) - close(phdr->backing_fd); - } - - free(ui->phdrs); - free(ui->note_phdr); - free(ui->threads); - - free(ui); -} diff --git a/contrib/libunwind/src/coredump/_UCD_elf_map_image.c b/contrib/libunwind/src/coredump/_UCD_elf_map_image.c deleted file mode 100644 index 4b3db0bbff7..00000000000 --- a/contrib/libunwind/src/coredump/_UCD_elf_map_image.c +++ /dev/null @@ -1,98 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "_UCD_lib.h" -#include "_UCD_internal.h" - -static coredump_phdr_t * -CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr) -{ - struct elf_image *ei = &ui->edi.ei; - - if (phdr->backing_fd < 0) - { - /* Note: coredump file contains only phdr->p_filesz bytes. - * We want to map bigger area (phdr->p_memsz bytes) to make sure - * these pages are allocated, but non-accessible. - */ - /* addr, length, prot, flags, fd, fd_offset */ - ei->image = mmap(NULL, phdr->p_memsz, PROT_READ, MAP_PRIVATE, ui->coredump_fd, phdr->p_offset); - if (ei->image == MAP_FAILED) - { - ei->image = NULL; - return NULL; - } - ei->size = phdr->p_filesz; - size_t remainder_len = phdr->p_memsz - phdr->p_filesz; - if (remainder_len > 0) - { - void *remainder_base = (char*) ei->image + phdr->p_filesz; - munmap(remainder_base, remainder_len); - } - } else { - /* We have a backing file for this segment. - * This file is always longer than phdr->p_memsz, - * and if phdr->p_filesz !=0, first phdr->p_filesz bytes in coredump - * are the same as first bytes in the file. (Thus no need to map coredump) - * We map the entire file: - * unwinding may need data which is past phdr->p_memsz bytes. - */ - /* addr, length, prot, flags, fd, fd_offset */ - ei->image = mmap(NULL, phdr->backing_filesize, PROT_READ, MAP_PRIVATE, phdr->backing_fd, 0); - if (ei->image == MAP_FAILED) - { - ei->image = NULL; - return NULL; - } - ei->size = phdr->backing_filesize; - } - - /* Check ELF header for sanity */ - if (!elf_w(valid_object)(ei)) - { - munmap(ei->image, ei->size); - ei->image = NULL; - ei->size = 0; - return NULL; - } - - return phdr; -} - -HIDDEN coredump_phdr_t * -_UCD_get_elf_image(struct UCD_info *ui, unw_word_t ip) -{ - unsigned i; - for (i = 0; i < ui->phdrs_count; i++) - { - coredump_phdr_t *phdr = &ui->phdrs[i]; - if (phdr->p_vaddr <= ip && ip < phdr->p_vaddr + phdr->p_memsz) - { - phdr = CD_elf_map_image(ui, phdr); - return phdr; - } - } - return NULL; -} diff --git a/contrib/libunwind/src/coredump/_UCD_find_proc_info.c b/contrib/libunwind/src/coredump/_UCD_find_proc_info.c deleted file mode 100644 index 33b66c8edbe..00000000000 --- a/contrib/libunwind/src/coredump/_UCD_find_proc_info.c +++ /dev/null @@ -1,163 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "_UCD_lib.h" -#include "_UCD_internal.h" - -static int -get_unwind_info(struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip) -{ - unsigned long segbase, mapoff; - -#if UNW_TARGET_IA64 && defined(__linux) - if (!ui->edi.ktab.start_ip && _Uia64_get_kernel_table (&ui->edi.ktab) < 0) - return -UNW_ENOINFO; - - if (ui->edi.ktab.format != -1 && ip >= ui->edi.ktab.start_ip && ip < ui->edi.ktab.end_ip) - return 0; -#endif - - if ((ui->edi.di_cache.format != -1 - && ip >= ui->edi.di_cache.start_ip && ip < ui->edi.di_cache.end_ip) -#if UNW_TARGET_ARM - || (ui->edi.di_debug.format != -1 - && ip >= ui->edi.di_arm.start_ip && ip < ui->edi.di_arm.end_ip) -#endif - || (ui->edi.di_debug.format != -1 - && ip >= ui->edi.di_debug.start_ip && ip < ui->edi.di_debug.end_ip)) - return 0; - - invalidate_edi (&ui->edi); - - /* Used to be tdep_get_elf_image() in ptrace unwinding code */ - coredump_phdr_t *phdr = _UCD_get_elf_image(ui, ip); - if (!phdr) - { - Debug(1, "returns error: _UCD_get_elf_image failed\n"); - return -UNW_ENOINFO; - } - /* segbase: where it is mapped in virtual memory */ - /* mapoff: offset in the file */ - segbase = phdr->p_vaddr; - /*mapoff = phdr->p_offset; WRONG! phdr->p_offset is the offset in COREDUMP file */ - mapoff = 0; -///FIXME. text segment is USUALLY, not always, at offset 0 in the binary/.so file. -// ensure that at initialization. - - /* Here, SEGBASE is the starting-address of the (mmap'ped) segment - which covers the IP we're looking for. */ - if (tdep_find_unwind_table(&ui->edi, as, phdr->backing_filename, segbase, mapoff, ip) < 0) - { - Debug(1, "returns error: tdep_find_unwind_table failed\n"); - return -UNW_ENOINFO; - } - - /* This can happen in corner cases where dynamically generated - code falls into the same page that contains the data-segment - and the page-offset of the code is within the first page of - the executable. */ - if (ui->edi.di_cache.format != -1 - && (ip < ui->edi.di_cache.start_ip || ip >= ui->edi.di_cache.end_ip)) - ui->edi.di_cache.format = -1; - - if (ui->edi.di_debug.format != -1 - && (ip < ui->edi.di_debug.start_ip || ip >= ui->edi.di_debug.end_ip)) - ui->edi.di_debug.format = -1; - - if (ui->edi.di_cache.format == -1 -#if UNW_TARGET_ARM - && ui->edi.di_arm.format == -1 -#endif - && ui->edi.di_debug.format == -1) - { - Debug(1, "returns error: all formats are -1\n"); - return -UNW_ENOINFO; - } - - Debug(1, "returns success\n"); - return 0; -} - -int -_UCD_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - struct UCD_info *ui = arg; - - Debug(1, "entering\n"); - - int ret = -UNW_ENOINFO; - - if (get_unwind_info(ui, as, ip) < 0) { - Debug(1, "returns error: get_unwind_info failed\n"); - return -UNW_ENOINFO; - } - -#if UNW_TARGET_IA64 - if (ui->edi.ktab.format != -1) - { - /* The kernel unwind table resides in local memory, so we have - to use the local address space to search it. Since - _UCD_put_unwind_info() has no easy way of detecting this - case, we simply make a copy of the unwind-info, so - _UCD_put_unwind_info() can always free() the unwind-info - without ill effects. */ - ret = tdep_search_unwind_table (unw_local_addr_space, ip, &ui->edi.ktab, pi, - need_unwind_info, arg); - if (ret >= 0) - { - if (!need_unwind_info) - pi->unwind_info = NULL; - else - { - void *mem = malloc (pi->unwind_info_size); - - if (!mem) - return -UNW_ENOMEM; - memcpy (mem, pi->unwind_info, pi->unwind_info_size); - pi->unwind_info = mem; - } - } - } -#endif - - if (ret == -UNW_ENOINFO && ui->edi.di_cache.format != -1) - ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache, - pi, need_unwind_info, arg); - -#if UNW_TARGET_ARM - if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1) - ret = tdep_search_unwind_table (as, ip, &ui->edi.di_arm, pi, - need_unwind_info, arg); -#endif - - if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1) - ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi, - need_unwind_info, arg); - - Debug(1, "returns %d\n", ret); - - return ret; -} diff --git a/contrib/libunwind/src/coredump/_UCD_get_proc_name.c b/contrib/libunwind/src/coredump/_UCD_get_proc_name.c deleted file mode 100644 index 00096c48d07..00000000000 --- a/contrib/libunwind/src/coredump/_UCD_get_proc_name.c +++ /dev/null @@ -1,70 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UCD_lib.h" -#include "_UCD_internal.h" - - -/* Find the ELF image that contains IP and return the "closest" - procedure name, if there is one. With some caching, this could be - sped up greatly, but until an application materializes that's - sensitive to the performance of this routine, why bother... */ -static int -elf_w (CD_get_proc_name) (struct UCD_info *ui, unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp) -{ - unsigned long segbase, mapoff; - int ret; - - /* Used to be tdep_get_elf_image() in ptrace unwinding code */ - coredump_phdr_t *cphdr = _UCD_get_elf_image(ui, ip); - if (!cphdr) - { - Debug(1, "returns error: _UCD_get_elf_image failed\n"); - return -UNW_ENOINFO; - } - /* segbase: where it is mapped in virtual memory */ - /* mapoff: offset in the file */ - segbase = cphdr->p_vaddr; - /*mapoff = phdr->p_offset; WRONG! phdr->p_offset is the offset in COREDUMP file */ - mapoff = 0; - - ret = elf_w (get_proc_name_in_image) (as, &ui->edi.ei, segbase, mapoff, ip, buf, buf_len, offp); - - return ret; -} - -int -_UCD_get_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, void *arg) -{ - struct UCD_info *ui = arg; - -#if ELF_CLASS == ELFCLASS64 - return _Uelf64_CD_get_proc_name (ui, as, ip, buf, buf_len, offp); -#elif ELF_CLASS == ELFCLASS32 - return _Uelf32_CD_get_proc_name (ui, as, ip, buf, buf_len, offp); -#else - return -UNW_ENOINFO; -#endif -} diff --git a/contrib/libunwind/src/coredump/_UCD_internal.h b/contrib/libunwind/src/coredump/_UCD_internal.h deleted file mode 100644 index 3c95a2a0038..00000000000 --- a/contrib/libunwind/src/coredump/_UCD_internal.h +++ /dev/null @@ -1,105 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _UCD_internal_h -#define _UCD_internal_h - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_PROCFS_H -#include /* struct elf_prstatus */ -#endif -#include -#include -#include -#include -#include - -#include - -#include "libunwind_i.h" - - -#if SIZEOF_OFF_T == 4 -typedef uint32_t uoff_t; -#elif SIZEOF_OFF_T == 8 -typedef uint64_t uoff_t; -#else -# error Unknown size of off_t! -#endif - - -/* Similar to ELF phdrs. p_paddr element is absent, - * since it's always 0 in coredumps. - */ -struct coredump_phdr - { - uint32_t p_type; - uint32_t p_flags; - uoff_t p_offset; - uoff_t p_vaddr; - uoff_t p_filesz; - uoff_t p_memsz; - uoff_t p_align; - /* Data for backing file. If backing_fd < 0, there is no file */ - uoff_t backing_filesize; - char *backing_filename; /* for error meesages only */ - int backing_fd; - }; - -typedef struct coredump_phdr coredump_phdr_t; - -#if defined(HAVE_STRUCT_ELF_PRSTATUS) -#define PRSTATUS_STRUCT elf_prstatus -#elif defined(HAVE_STRUCT_PRSTATUS) -#define PRSTATUS_STRUCT prstatus -#else -#define PRSTATUS_STRUCT non_existent -#endif - -struct UCD_info - { - int big_endian; /* bool */ - int coredump_fd; - char *coredump_filename; /* for error meesages only */ - coredump_phdr_t *phdrs; /* array, allocated */ - unsigned phdrs_count; - void *note_phdr; /* allocated or NULL */ - struct PRSTATUS_STRUCT *prstatus; /* points inside note_phdr */ - int n_threads; - struct PRSTATUS_STRUCT **threads; - - struct elf_dyn_info edi; - }; - -extern coredump_phdr_t * _UCD_get_elf_image(struct UCD_info *ui, unw_word_t ip); - -#define STRUCT_MEMBER_P(struct_p, struct_offset) ((void *) ((char*) (struct_p) + (long) (struct_offset))) -#define STRUCT_MEMBER(member_type, struct_p, struct_offset) (*(member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset))) - -#endif diff --git a/contrib/libunwind/src/coredump/_UCD_lib.h b/contrib/libunwind/src/coredump/_UCD_lib.h deleted file mode 100644 index 22be32ed1ef..00000000000 --- a/contrib/libunwind/src/coredump/_UCD_lib.h +++ /dev/null @@ -1,57 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _UCD_lib_h -#define _UCD_lib_h - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif diff --git a/contrib/libunwind/src/coredump/_UPT_access_fpreg.c b/contrib/libunwind/src/coredump/_UPT_access_fpreg.c deleted file mode 100644 index 0b8b86ac907..00000000000 --- a/contrib/libunwind/src/coredump/_UPT_access_fpreg.c +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UCD_lib.h" -#include "_UCD_internal.h" - -int -_UCD_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - print_error (__func__); - print_error (" not implemented\n"); - return -UNW_EINVAL; -} diff --git a/contrib/libunwind/src/coredump/_UPT_elf.c b/contrib/libunwind/src/coredump/_UPT_elf.c deleted file mode 100644 index fb7b19a7cbd..00000000000 --- a/contrib/libunwind/src/coredump/_UPT_elf.c +++ /dev/null @@ -1,5 +0,0 @@ -/* We need to get a separate copy of the ELF-code into - libunwind-coredump since it cannot (and must not) have any ELF - dependencies on libunwind. */ -#include "libunwind_i.h" /* get ELFCLASS defined */ -#include "../elfxx.c" diff --git a/contrib/libunwind/src/coredump/_UPT_get_dyn_info_list_addr.c b/contrib/libunwind/src/coredump/_UPT_get_dyn_info_list_addr.c deleted file mode 100644 index 0d11905566c..00000000000 --- a/contrib/libunwind/src/coredump/_UPT_get_dyn_info_list_addr.c +++ /dev/null @@ -1,108 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UCD_lib.h" -#include "_UCD_internal.h" - -#if UNW_TARGET_IA64 && defined(__linux) -# include "elf64.h" -# include "os-linux.h" - -static inline int -get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg, - int *countp) -{ - unsigned long lo, hi, off; - struct UPT_info *ui = arg; - struct map_iterator mi; - char path[PATH_MAX]; - unw_dyn_info_t *di; - unw_word_t res; - int count = 0; - - maps_init (&mi, ui->pid); - while (maps_next (&mi, &lo, &hi, &off)) - { - if (off) - continue; - - invalidate_edi (&ui->edi); - - if (elf_map_image (&ui->ei, path) < 0) - /* ignore unmappable stuff like "/SYSV00001b58 (deleted)" */ - continue; - - Debug (16, "checking object %s\n", path); - - di = tdep_find_unwind_table (&ui->edi, as, path, lo, off); - if (di) - { - res = _Uia64_find_dyn_list (as, di, arg); - if (res && count++ == 0) - { - Debug (12, "dyn_info_list_addr = 0x%lx\n", (long) res); - *dil_addr = res; - } - } - } - maps_close (&mi); - *countp = count; - return 0; -} - -#else - -static inline int -get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg, - int *countp) -{ -# warning Implement get_list_addr(), please. - *countp = 0; - return 0; -} - -#endif - -int -_UCD_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, - void *arg) -{ - int count, ret; - - Debug (12, "looking for dyn_info list\n"); - - if ((ret = get_list_addr (as, dil_addr, arg, &count)) < 0) - return ret; - - /* If multiple dynamic-info list addresses are found, we would have - to determine which was is the one actually in use (since the - dynamic name resolution algorithm will pick one "winner"). - Perhaps we'd have to track them all until we find one that's - non-empty. Hopefully, this case simply will never arise, since - only libunwind defines the dynamic info list head. */ - assert (count <= 1); - - return (count > 0) ? 0 : -UNW_ENOINFO; -} diff --git a/contrib/libunwind/src/coredump/_UPT_put_unwind_info.c b/contrib/libunwind/src/coredump/_UPT_put_unwind_info.c deleted file mode 100644 index 462e1d048c3..00000000000 --- a/contrib/libunwind/src/coredump/_UPT_put_unwind_info.c +++ /dev/null @@ -1,36 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UCD_lib.h" -#include "_UCD_internal.h" - -void -_UCD_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg) -{ - if (!pi->unwind_info) - return; - free (pi->unwind_info); - pi->unwind_info = NULL; -} diff --git a/contrib/libunwind/src/coredump/_UPT_resume.c b/contrib/libunwind/src/coredump/_UPT_resume.c deleted file mode 100644 index a729c908cb1..00000000000 --- a/contrib/libunwind/src/coredump/_UPT_resume.c +++ /dev/null @@ -1,35 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UCD_lib.h" -#include "_UCD_internal.h" - -int -_UCD_resume (unw_addr_space_t as, unw_cursor_t *c, void *arg) -{ - print_error (__func__); - print_error (" not implemented\n"); - return -UNW_EINVAL; -} diff --git a/contrib/libunwind/src/coredump/libunwind-coredump.pc.in b/contrib/libunwind/src/coredump/libunwind-coredump.pc.in deleted file mode 100644 index 9cb62c086d2..00000000000 --- a/contrib/libunwind/src/coredump/libunwind-coredump.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libunwind-coredump -Description: libunwind coredump library -Version: @VERSION@ -Requires: libunwind-generic libunwind -Libs: -L${libdir} -lunwind-coredump -Cflags: -I${includedir} diff --git a/contrib/libunwind/src/dwarf/Gexpr.c b/contrib/libunwind/src/dwarf/Gexpr.c deleted file mode 100644 index 4da28be6203..00000000000 --- a/contrib/libunwind/src/dwarf/Gexpr.c +++ /dev/null @@ -1,696 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "dwarf_i.h" -#include "libunwind_i.h" - -/* The "pick" operator provides an index range of 0..255 indicating - that the stack could at least have a depth of up to 256 elements, - but the GCC unwinder restricts the depth to 64, which seems - reasonable so we use the same value here. */ -#define MAX_EXPR_STACK_SIZE 64 - -#define NUM_OPERANDS(signature) (((signature) >> 6) & 0x3) -#define OPND1_TYPE(signature) (((signature) >> 3) & 0x7) -#define OPND2_TYPE(signature) (((signature) >> 0) & 0x7) - -#define OPND_SIGNATURE(n, t1, t2) (((n) << 6) | ((t1) << 3) | ((t2) << 0)) -#define OPND1(t1) OPND_SIGNATURE(1, t1, 0) -#define OPND2(t1, t2) OPND_SIGNATURE(2, t1, t2) - -#define VAL8 0x0 -#define VAL16 0x1 -#define VAL32 0x2 -#define VAL64 0x3 -#define ULEB128 0x4 -#define SLEB128 0x5 -#define OFFSET 0x6 /* 32-bit offset for 32-bit DWARF, 64-bit otherwise */ -#define ADDR 0x7 /* Machine address. */ - -static const uint8_t operands[256] = - { - [DW_OP_addr] = OPND1 (ADDR), - [DW_OP_const1u] = OPND1 (VAL8), - [DW_OP_const1s] = OPND1 (VAL8), - [DW_OP_const2u] = OPND1 (VAL16), - [DW_OP_const2s] = OPND1 (VAL16), - [DW_OP_const4u] = OPND1 (VAL32), - [DW_OP_const4s] = OPND1 (VAL32), - [DW_OP_const8u] = OPND1 (VAL64), - [DW_OP_const8s] = OPND1 (VAL64), - [DW_OP_pick] = OPND1 (VAL8), - [DW_OP_plus_uconst] = OPND1 (ULEB128), - [DW_OP_skip] = OPND1 (VAL16), - [DW_OP_bra] = OPND1 (VAL16), - [DW_OP_breg0 + 0] = OPND1 (SLEB128), - [DW_OP_breg0 + 1] = OPND1 (SLEB128), - [DW_OP_breg0 + 2] = OPND1 (SLEB128), - [DW_OP_breg0 + 3] = OPND1 (SLEB128), - [DW_OP_breg0 + 4] = OPND1 (SLEB128), - [DW_OP_breg0 + 5] = OPND1 (SLEB128), - [DW_OP_breg0 + 6] = OPND1 (SLEB128), - [DW_OP_breg0 + 7] = OPND1 (SLEB128), - [DW_OP_breg0 + 8] = OPND1 (SLEB128), - [DW_OP_breg0 + 9] = OPND1 (SLEB128), - [DW_OP_breg0 + 10] = OPND1 (SLEB128), - [DW_OP_breg0 + 11] = OPND1 (SLEB128), - [DW_OP_breg0 + 12] = OPND1 (SLEB128), - [DW_OP_breg0 + 13] = OPND1 (SLEB128), - [DW_OP_breg0 + 14] = OPND1 (SLEB128), - [DW_OP_breg0 + 15] = OPND1 (SLEB128), - [DW_OP_breg0 + 16] = OPND1 (SLEB128), - [DW_OP_breg0 + 17] = OPND1 (SLEB128), - [DW_OP_breg0 + 18] = OPND1 (SLEB128), - [DW_OP_breg0 + 19] = OPND1 (SLEB128), - [DW_OP_breg0 + 20] = OPND1 (SLEB128), - [DW_OP_breg0 + 21] = OPND1 (SLEB128), - [DW_OP_breg0 + 22] = OPND1 (SLEB128), - [DW_OP_breg0 + 23] = OPND1 (SLEB128), - [DW_OP_breg0 + 24] = OPND1 (SLEB128), - [DW_OP_breg0 + 25] = OPND1 (SLEB128), - [DW_OP_breg0 + 26] = OPND1 (SLEB128), - [DW_OP_breg0 + 27] = OPND1 (SLEB128), - [DW_OP_breg0 + 28] = OPND1 (SLEB128), - [DW_OP_breg0 + 29] = OPND1 (SLEB128), - [DW_OP_breg0 + 30] = OPND1 (SLEB128), - [DW_OP_breg0 + 31] = OPND1 (SLEB128), - [DW_OP_regx] = OPND1 (ULEB128), - [DW_OP_fbreg] = OPND1 (SLEB128), - [DW_OP_bregx] = OPND2 (ULEB128, SLEB128), - [DW_OP_piece] = OPND1 (ULEB128), - [DW_OP_deref_size] = OPND1 (VAL8), - [DW_OP_xderef_size] = OPND1 (VAL8), - [DW_OP_call2] = OPND1 (VAL16), - [DW_OP_call4] = OPND1 (VAL32), - [DW_OP_call_ref] = OPND1 (OFFSET) - }; - -static inline unw_sword_t -sword (unw_addr_space_t as, unw_word_t val) -{ - switch (dwarf_addr_size (as)) - { - case 1: return (int8_t) val; - case 2: return (int16_t) val; - case 4: return (int32_t) val; - case 8: return (int64_t) val; - default: abort (); - } -} - -static inline unw_word_t -read_operand (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, int operand_type, unw_word_t *val, void *arg) -{ - uint8_t u8; - uint16_t u16; - uint32_t u32; - uint64_t u64; - int ret; - - if (operand_type == ADDR) - switch (dwarf_addr_size (as)) - { - case 1: operand_type = VAL8; break; - case 2: operand_type = VAL16; break; - case 4: operand_type = VAL32; break; - case 8: operand_type = VAL64; break; - default: abort (); - } - - switch (operand_type) - { - case VAL8: - ret = dwarf_readu8 (as, a, addr, &u8, arg); - if (ret < 0) - return ret; - *val = u8; - break; - - case VAL16: - ret = dwarf_readu16 (as, a, addr, &u16, arg); - if (ret < 0) - return ret; - *val = u16; - break; - - case VAL32: - ret = dwarf_readu32 (as, a, addr, &u32, arg); - if (ret < 0) - return ret; - *val = u32; - break; - - case VAL64: - ret = dwarf_readu64 (as, a, addr, &u64, arg); - if (ret < 0) - return ret; - *val = u64; - break; - - case ULEB128: - ret = dwarf_read_uleb128 (as, a, addr, val, arg); - break; - - case SLEB128: - ret = dwarf_read_sleb128 (as, a, addr, val, arg); - break; - - case OFFSET: /* only used by DW_OP_call_ref, which we don't implement */ - default: - Debug (1, "Unexpected operand type %d\n", operand_type); - ret = -UNW_EINVAL; - } - return ret; -} - -HIDDEN int -dwarf_stack_aligned(struct dwarf_cursor *c, unw_word_t cfa_addr, - unw_word_t rbp_addr, unw_word_t *cfa_offset) { - unw_accessors_t *a; - int ret; - void *arg; - unw_word_t len; - uint8_t opcode; - unw_word_t operand1; - - a = unw_get_accessors (c->as); - arg = c->as_arg; - - ret = dwarf_read_uleb128(c->as, a, &rbp_addr, &len, arg); - if (len != 2 || ret < 0) - return 0; - - ret = dwarf_readu8(c->as, a, &rbp_addr, &opcode, arg); - if (ret < 0 || opcode != DW_OP_breg6) - return 0; - - ret = read_operand(c->as, a, &rbp_addr, - OPND1_TYPE(operands[opcode]), &operand1, arg); - - if (ret < 0 || operand1 != 0) - return 0; - - ret = dwarf_read_uleb128(c->as, a, &cfa_addr, &len, arg); - if (ret < 0 || len != 3) - return 0; - - ret = dwarf_readu8(c->as, a, &cfa_addr, &opcode, arg); - if (ret < 0 || opcode != DW_OP_breg6) - return 0; - - ret = read_operand(c->as, a, &cfa_addr, - OPND1_TYPE(operands[opcode]), &operand1, arg); - if (ret < 0) - return 0; - - ret = dwarf_readu8(c->as, a, &cfa_addr, &opcode, arg); - if (ret < 0 || opcode != DW_OP_deref) - return 0; - - *cfa_offset = operand1; - return 1; -} - -HIDDEN int -dwarf_eval_expr (struct dwarf_cursor *c, unw_word_t *addr, unw_word_t len, - unw_word_t *valp, int *is_register) -{ - unw_word_t operand1 = 0, operand2 = 0, tmp1, tmp2 = 0, tmp3, end_addr; - uint8_t opcode, operands_signature, u8; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - unw_word_t stack[MAX_EXPR_STACK_SIZE]; - unsigned int tos = 0; - uint16_t u16; - uint32_t u32; - uint64_t u64; - int ret; -# define pop() \ -({ \ - if ((tos - 1) >= MAX_EXPR_STACK_SIZE) \ - { \ - Debug (1, "Stack underflow\n"); \ - return -UNW_EINVAL; \ - } \ - stack[--tos]; \ -}) -# define push(x) \ -do { \ - unw_word_t _x = (x); \ - if (tos >= MAX_EXPR_STACK_SIZE) \ - { \ - Debug (1, "Stack overflow\n"); \ - return -UNW_EINVAL; \ - } \ - stack[tos++] = _x; \ -} while (0) -# define pick(n) \ -({ \ - unsigned int _index = tos - 1 - (n); \ - if (_index >= MAX_EXPR_STACK_SIZE) \ - { \ - Debug (1, "Out-of-stack pick\n"); \ - return -UNW_EINVAL; \ - } \ - stack[_index]; \ -}) - - as = c->as; - arg = c->as_arg; - a = unw_get_accessors (as); - end_addr = *addr + len; - *is_register = 0; - - Debug (14, "len=%lu, pushing cfa=0x%lx\n", - (unsigned long) len, (unsigned long) c->cfa); - - push (c->cfa); /* push current CFA as required by DWARF spec */ - - while (*addr < end_addr) - { - if ((ret = dwarf_readu8 (as, a, addr, &opcode, arg)) < 0) - return ret; - - operands_signature = operands[opcode]; - - if (unlikely (NUM_OPERANDS (operands_signature) > 0)) - { - if ((ret = read_operand (as, a, addr, - OPND1_TYPE (operands_signature), - &operand1, arg)) < 0) - return ret; - if (NUM_OPERANDS (operands_signature) > 1) - if ((ret = read_operand (as, a, addr, - OPND2_TYPE (operands_signature), - &operand2, arg)) < 0) - return ret; - } - - switch ((dwarf_expr_op_t) opcode) - { - case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: - case DW_OP_lit3: case DW_OP_lit4: case DW_OP_lit5: - case DW_OP_lit6: case DW_OP_lit7: case DW_OP_lit8: - case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11: - case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: - case DW_OP_lit15: case DW_OP_lit16: case DW_OP_lit17: - case DW_OP_lit18: case DW_OP_lit19: case DW_OP_lit20: - case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23: - case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26: - case DW_OP_lit27: case DW_OP_lit28: case DW_OP_lit29: - case DW_OP_lit30: case DW_OP_lit31: - Debug (15, "OP_lit(%d)\n", (int) opcode - DW_OP_lit0); - push (opcode - DW_OP_lit0); - break; - - case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: - case DW_OP_breg3: case DW_OP_breg4: case DW_OP_breg5: - case DW_OP_breg6: case DW_OP_breg7: case DW_OP_breg8: - case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11: - case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: - case DW_OP_breg15: case DW_OP_breg16: case DW_OP_breg17: - case DW_OP_breg18: case DW_OP_breg19: case DW_OP_breg20: - case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23: - case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: - case DW_OP_breg27: case DW_OP_breg28: case DW_OP_breg29: - case DW_OP_breg30: case DW_OP_breg31: - Debug (15, "OP_breg(r%d,0x%lx)\n", - (int) opcode - DW_OP_breg0, (unsigned long) operand1); - if ((ret = unw_get_reg (dwarf_to_cursor (c), - dwarf_to_unw_regnum (opcode - DW_OP_breg0), - &tmp1)) < 0) - return ret; - push (tmp1 + operand1); - break; - - case DW_OP_bregx: - Debug (15, "OP_bregx(r%d,0x%lx)\n", - (int) operand1, (unsigned long) operand2); - if ((ret = unw_get_reg (dwarf_to_cursor (c), - dwarf_to_unw_regnum (operand1), &tmp1)) < 0) - return ret; - push (tmp1 + operand2); - break; - - case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2: - case DW_OP_reg3: case DW_OP_reg4: case DW_OP_reg5: - case DW_OP_reg6: case DW_OP_reg7: case DW_OP_reg8: - case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11: - case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: - case DW_OP_reg15: case DW_OP_reg16: case DW_OP_reg17: - case DW_OP_reg18: case DW_OP_reg19: case DW_OP_reg20: - case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23: - case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: - case DW_OP_reg27: case DW_OP_reg28: case DW_OP_reg29: - case DW_OP_reg30: case DW_OP_reg31: - Debug (15, "OP_reg(r%d)\n", (int) opcode - DW_OP_reg0); - *valp = dwarf_to_unw_regnum (opcode - DW_OP_reg0); - *is_register = 1; - return 0; - - case DW_OP_regx: - Debug (15, "OP_regx(r%d)\n", (int) operand1); - *valp = dwarf_to_unw_regnum (operand1); - *is_register = 1; - return 0; - - case DW_OP_addr: - case DW_OP_const1u: - case DW_OP_const2u: - case DW_OP_const4u: - case DW_OP_const8u: - case DW_OP_constu: - case DW_OP_const8s: - case DW_OP_consts: - Debug (15, "OP_const(0x%lx)\n", (unsigned long) operand1); - push (operand1); - break; - - case DW_OP_const1s: - if (operand1 & 0x80) - operand1 |= ((unw_word_t) -1) << 8; - Debug (15, "OP_const1s(%ld)\n", (long) operand1); - push (operand1); - break; - - case DW_OP_const2s: - if (operand1 & 0x8000) - operand1 |= ((unw_word_t) -1) << 16; - Debug (15, "OP_const2s(%ld)\n", (long) operand1); - push (operand1); - break; - - case DW_OP_const4s: - if (operand1 & 0x80000000) - operand1 |= (((unw_word_t) -1) << 16) << 16; - Debug (15, "OP_const4s(%ld)\n", (long) operand1); - push (operand1); - break; - - case DW_OP_deref: - Debug (15, "OP_deref\n"); - tmp1 = pop (); - if ((ret = dwarf_readw (as, a, &tmp1, &tmp2, arg)) < 0) - return ret; - push (tmp2); - break; - - case DW_OP_deref_size: - Debug (15, "OP_deref_size(%d)\n", (int) operand1); - tmp1 = pop (); - switch (operand1) - { - default: - Debug (1, "Unexpected DW_OP_deref_size size %d\n", - (int) operand1); - return -UNW_EINVAL; - - case 1: - if ((ret = dwarf_readu8 (as, a, &tmp1, &u8, arg)) < 0) - return ret; - tmp2 = u8; - break; - - case 2: - if ((ret = dwarf_readu16 (as, a, &tmp1, &u16, arg)) < 0) - return ret; - tmp2 = u16; - break; - - case 3: - case 4: - if ((ret = dwarf_readu32 (as, a, &tmp1, &u32, arg)) < 0) - return ret; - tmp2 = u32; - if (operand1 == 3) - { - if (dwarf_is_big_endian (as)) - tmp2 >>= 8; - else - tmp2 &= 0xffffff; - } - break; - case 5: - case 6: - case 7: - case 8: - if ((ret = dwarf_readu64 (as, a, &tmp1, &u64, arg)) < 0) - return ret; - tmp2 = u64; - if (operand1 != 8) - { - if (dwarf_is_big_endian (as)) - tmp2 >>= 64 - 8 * operand1; - else - tmp2 &= (~ (unw_word_t) 0) << (8 * operand1); - } - break; - } - push (tmp2); - break; - - case DW_OP_dup: - Debug (15, "OP_dup\n"); - push (pick (0)); - break; - - case DW_OP_drop: - Debug (15, "OP_drop\n"); - (void) pop (); - break; - - case DW_OP_pick: - Debug (15, "OP_pick(%d)\n", (int) operand1); - push (pick (operand1)); - break; - - case DW_OP_over: - Debug (15, "OP_over\n"); - push (pick (1)); - break; - - case DW_OP_swap: - Debug (15, "OP_swap\n"); - tmp1 = pop (); - tmp2 = pop (); - push (tmp1); - push (tmp2); - break; - - case DW_OP_rot: - Debug (15, "OP_rot\n"); - tmp1 = pop (); - tmp2 = pop (); - tmp3 = pop (); - push (tmp1); - push (tmp3); - push (tmp2); - break; - - case DW_OP_abs: - Debug (15, "OP_abs\n"); - tmp1 = pop (); - if (tmp1 & ((unw_word_t) 1 << (8 * dwarf_addr_size (as) - 1))) - tmp1 = -tmp1; - push (tmp1); - break; - - case DW_OP_and: - Debug (15, "OP_and\n"); - tmp1 = pop (); - tmp2 = pop (); - push (tmp1 & tmp2); - break; - - case DW_OP_div: - Debug (15, "OP_div\n"); - tmp1 = pop (); - tmp2 = pop (); - if (tmp1) - tmp1 = sword (as, tmp2) / sword (as, tmp1); - push (tmp1); - break; - - case DW_OP_minus: - Debug (15, "OP_minus\n"); - tmp1 = pop (); - tmp2 = pop (); - tmp1 = tmp2 - tmp1; - push (tmp1); - break; - - case DW_OP_mod: - Debug (15, "OP_mod\n"); - tmp1 = pop (); - tmp2 = pop (); - if (tmp1) - tmp1 = tmp2 % tmp1; - push (tmp1); - break; - - case DW_OP_mul: - Debug (15, "OP_mul\n"); - tmp1 = pop (); - tmp2 = pop (); - if (tmp1) - tmp1 = tmp2 * tmp1; - push (tmp1); - break; - - case DW_OP_neg: - Debug (15, "OP_neg\n"); - push (-pop ()); - break; - - case DW_OP_not: - Debug (15, "OP_not\n"); - push (~pop ()); - break; - - case DW_OP_or: - Debug (15, "OP_or\n"); - tmp1 = pop (); - tmp2 = pop (); - push (tmp1 | tmp2); - break; - - case DW_OP_plus: - Debug (15, "OP_plus\n"); - tmp1 = pop (); - tmp2 = pop (); - push (tmp1 + tmp2); - break; - - case DW_OP_plus_uconst: - Debug (15, "OP_plus_uconst(%lu)\n", (unsigned long) operand1); - tmp1 = pop (); - push (tmp1 + operand1); - break; - - case DW_OP_shl: - Debug (15, "OP_shl\n"); - tmp1 = pop (); - tmp2 = pop (); - push (tmp2 << tmp1); - break; - - case DW_OP_shr: - Debug (15, "OP_shr\n"); - tmp1 = pop (); - tmp2 = pop (); - push (tmp2 >> tmp1); - break; - - case DW_OP_shra: - Debug (15, "OP_shra\n"); - tmp1 = pop (); - tmp2 = pop (); - push (sword (as, tmp2) >> tmp1); - break; - - case DW_OP_xor: - Debug (15, "OP_xor\n"); - tmp1 = pop (); - tmp2 = pop (); - push (tmp1 ^ tmp2); - break; - - case DW_OP_le: - Debug (15, "OP_le\n"); - tmp1 = pop (); - tmp2 = pop (); - push (sword (as, tmp2) <= sword (as, tmp1)); - break; - - case DW_OP_ge: - Debug (15, "OP_ge\n"); - tmp1 = pop (); - tmp2 = pop (); - push (sword (as, tmp2) >= sword (as, tmp1)); - break; - - case DW_OP_eq: - Debug (15, "OP_eq\n"); - tmp1 = pop (); - tmp2 = pop (); - push (sword (as, tmp2) == sword (as, tmp1)); - break; - - case DW_OP_lt: - Debug (15, "OP_lt\n"); - tmp1 = pop (); - tmp2 = pop (); - push (sword (as, tmp2) < sword (as, tmp1)); - break; - - case DW_OP_gt: - Debug (15, "OP_gt\n"); - tmp1 = pop (); - tmp2 = pop (); - push (sword (as, tmp2) > sword (as, tmp1)); - break; - - case DW_OP_ne: - Debug (15, "OP_ne\n"); - tmp1 = pop (); - tmp2 = pop (); - push (sword (as, tmp2) != sword (as, tmp1)); - break; - - case DW_OP_skip: - Debug (15, "OP_skip(%d)\n", (int16_t) operand1); - *addr += (int16_t) operand1; - break; - - case DW_OP_bra: - Debug (15, "OP_skip(%d)\n", (int16_t) operand1); - tmp1 = pop (); - if (tmp1) - *addr += (int16_t) operand1; - break; - - case DW_OP_nop: - Debug (15, "OP_nop\n"); - break; - - case DW_OP_call2: - case DW_OP_call4: - case DW_OP_call_ref: - case DW_OP_fbreg: - case DW_OP_piece: - case DW_OP_push_object_address: - case DW_OP_xderef: - case DW_OP_xderef_size: - default: - Debug (1, "Unexpected opcode 0x%x\n", opcode); - return -UNW_EINVAL; - } - } - *valp = pop (); - Debug (14, "final value = 0x%lx\n", (unsigned long) *valp); - return 0; -} diff --git a/contrib/libunwind/src/dwarf/Gfde.c b/contrib/libunwind/src/dwarf/Gfde.c deleted file mode 100644 index 49484eee131..00000000000 --- a/contrib/libunwind/src/dwarf/Gfde.c +++ /dev/null @@ -1,358 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "dwarf_i.h" - -static inline int -is_cie_id (unw_word_t val, int is_debug_frame) -{ - /* The CIE ID is normally 0xffffffff (for 32-bit ELF) or - 0xffffffffffffffff (for 64-bit ELF). However, .eh_frame - uses 0. */ - if (is_debug_frame) - return (val == (uint32_t)(-1) || val == (uint64_t)(-1)); - else - return (val == 0); -} - -/* Note: we don't need to keep track of more than the first four - characters of the augmentation string, because we (a) ignore any - augmentation string contents once we find an unrecognized character - and (b) those characters that we do recognize, can't be - repeated. */ -static inline int -parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr, - const unw_proc_info_t *pi, struct dwarf_cie_info *dci, - int is_debug_frame, void *arg) -{ - uint8_t version, ch, augstr[5], fde_encoding, handler_encoding; - unw_word_t len, cie_end_addr, aug_size; - uint32_t u32val; - uint64_t u64val; - size_t i; - int ret; -# define STR2(x) #x -# define STR(x) STR2(x) - - /* Pick appropriate default for FDE-encoding. DWARF spec says - start-IP (initial_location) and the code-size (address_range) are - "address-unit sized constants". The `R' augmentation can be used - to override this, but by default, we pick an address-sized unit - for fde_encoding. */ - switch (dwarf_addr_size (as)) - { - case 4: fde_encoding = DW_EH_PE_udata4; break; - case 8: fde_encoding = DW_EH_PE_udata8; break; - default: fde_encoding = DW_EH_PE_omit; break; - } - - dci->lsda_encoding = DW_EH_PE_omit; - dci->handler = 0; - - if ((ret = dwarf_readu32 (as, a, &addr, &u32val, arg)) < 0) - return ret; - - if (u32val != 0xffffffff) - { - /* the CIE is in the 32-bit DWARF format */ - uint32_t cie_id; - /* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */ - const uint32_t expected_id = (is_debug_frame) ? 0xffffffff : 0; - - len = u32val; - cie_end_addr = addr + len; - if ((ret = dwarf_readu32 (as, a, &addr, &cie_id, arg)) < 0) - return ret; - if (cie_id != expected_id) - { - Debug (1, "Unexpected CIE id %x\n", cie_id); - return -UNW_EINVAL; - } - } - else - { - /* the CIE is in the 64-bit DWARF format */ - uint64_t cie_id; - /* DWARF says CIE id should be 0xffffffffffffffff, but in - .eh_frame, it's 0 */ - const uint64_t expected_id = (is_debug_frame) ? 0xffffffffffffffffull : 0; - - if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0) - return ret; - len = u64val; - cie_end_addr = addr + len; - if ((ret = dwarf_readu64 (as, a, &addr, &cie_id, arg)) < 0) - return ret; - if (cie_id != expected_id) - { - Debug (1, "Unexpected CIE id %llx\n", (long long) cie_id); - return -UNW_EINVAL; - } - } - dci->cie_instr_end = cie_end_addr; - - if ((ret = dwarf_readu8 (as, a, &addr, &version, arg)) < 0) - return ret; - - if (version != 1 && version != DWARF_CIE_VERSION) - { - Debug (1, "Got CIE version %u, expected version 1 or " - STR (DWARF_CIE_VERSION) "\n", version); - return -UNW_EBADVERSION; - } - - /* read and parse the augmentation string: */ - memset (augstr, 0, sizeof (augstr)); - for (i = 0;;) - { - if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0) - return ret; - - if (!ch) - break; /* end of augmentation string */ - - if (i < sizeof (augstr) - 1) - augstr[i++] = ch; - } - - if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->code_align, arg)) < 0 - || (ret = dwarf_read_sleb128 (as, a, &addr, &dci->data_align, arg)) < 0) - return ret; - - /* Read the return-address column either as a u8 or as a uleb128. */ - if (version == 1) - { - if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0) - return ret; - dci->ret_addr_column = ch; - } - else if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->ret_addr_column, - arg)) < 0) - return ret; - - i = 0; - if (augstr[0] == 'z') - { - dci->sized_augmentation = 1; - if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0) - return ret; - i++; - } - - for (; i < sizeof (augstr) && augstr[i]; ++i) - switch (augstr[i]) - { - case 'L': - /* read the LSDA pointer-encoding format. */ - if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0) - return ret; - dci->lsda_encoding = ch; - break; - - case 'R': - /* read the FDE pointer-encoding format. */ - if ((ret = dwarf_readu8 (as, a, &addr, &fde_encoding, arg)) < 0) - return ret; - break; - - case 'P': - /* read the personality-routine pointer-encoding format. */ - if ((ret = dwarf_readu8 (as, a, &addr, &handler_encoding, arg)) < 0) - return ret; - if ((ret = dwarf_read_encoded_pointer (as, a, &addr, handler_encoding, - pi, &dci->handler, arg)) < 0) - return ret; - break; - - case 'S': - /* This is a signal frame. */ - dci->signal_frame = 1; - - /* Temporarily set it to one so dwarf_parse_fde() knows that - it should fetch the actual ABI/TAG pair from the FDE. */ - dci->have_abi_marker = 1; - break; - - default: - Debug (1, "Unexpected augmentation string `%s'\n", augstr); - if (dci->sized_augmentation) - /* If we have the size of the augmentation body, we can skip - over the parts that we don't understand, so we're OK. */ - goto done; - else - return -UNW_EINVAL; - } - done: - dci->fde_encoding = fde_encoding; - dci->cie_instr_start = addr; - Debug (15, "CIE parsed OK, augmentation = \"%s\", handler=0x%lx\n", - augstr, (long) dci->handler); - return 0; -} - -/* Extract proc-info from the FDE starting at adress ADDR. - - Pass BASE as zero for eh_frame behaviour, or a pointer to - debug_frame base for debug_frame behaviour. */ - -HIDDEN int -dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addrp, unw_proc_info_t *pi, - unw_word_t base, - int need_unwind_info, int is_debug_frame, - void *arg) -{ - unw_word_t fde_end_addr, cie_addr, cie_offset_addr, aug_end_addr = 0; - unw_word_t start_ip, ip_range, aug_size, addr = *addrp; - int ret, ip_range_encoding; - struct dwarf_cie_info dci; - uint64_t u64val; - uint32_t u32val; - - Debug (12, "FDE @ 0x%lx\n", (long) addr); - - memset (&dci, 0, sizeof (dci)); - - if ((ret = dwarf_readu32 (as, a, &addr, &u32val, arg)) < 0) - return ret; - - if (u32val != 0xffffffff) - { - int32_t cie_offset = 0; - - /* In some configurations, an FDE with a 0 length indicates the - end of the FDE-table. */ - if (u32val == 0) - return -UNW_ENOINFO; - - /* the FDE is in the 32-bit DWARF format */ - - *addrp = fde_end_addr = addr + u32val; - cie_offset_addr = addr; - - if ((ret = dwarf_reads32 (as, a, &addr, &cie_offset, arg)) < 0) - return ret; - - if (is_cie_id (cie_offset, is_debug_frame)) - /* ignore CIEs (happens during linear searches) */ - return 0; - - if (is_debug_frame) - cie_addr = base + cie_offset; - else - /* DWARF says that the CIE_pointer in the FDE is a - .debug_frame-relative offset, but the GCC-generated .eh_frame - sections instead store a "pcrelative" offset, which is just - as fine as it's self-contained. */ - cie_addr = cie_offset_addr - cie_offset; - } - else - { - int64_t cie_offset = 0; - - /* the FDE is in the 64-bit DWARF format */ - - if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0) - return ret; - - *addrp = fde_end_addr = addr + u64val; - cie_offset_addr = addr; - - if ((ret = dwarf_reads64 (as, a, &addr, &cie_offset, arg)) < 0) - return ret; - - if (is_cie_id (cie_offset, is_debug_frame)) - /* ignore CIEs (happens during linear searches) */ - return 0; - - if (is_debug_frame) - cie_addr = base + cie_offset; - else - /* DWARF says that the CIE_pointer in the FDE is a - .debug_frame-relative offset, but the GCC-generated .eh_frame - sections instead store a "pcrelative" offset, which is just - as fine as it's self-contained. */ - cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset); - } - - Debug (15, "looking for CIE at address %lx\n", (long) cie_addr); - - if ((ret = parse_cie (as, a, cie_addr, pi, &dci, is_debug_frame, arg)) < 0) - return ret; - - /* IP-range has same encoding as FDE pointers, except that it's - always an absolute value: */ - ip_range_encoding = dci.fde_encoding & DW_EH_PE_FORMAT_MASK; - - if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.fde_encoding, - pi, &start_ip, arg)) < 0 - || (ret = dwarf_read_encoded_pointer (as, a, &addr, ip_range_encoding, - pi, &ip_range, arg)) < 0) - return ret; - pi->start_ip = start_ip; - pi->end_ip = start_ip + ip_range; - pi->handler = dci.handler; - - if (dci.sized_augmentation) - { - if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0) - return ret; - aug_end_addr = addr + aug_size; - } - - if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.lsda_encoding, - pi, &pi->lsda, arg)) < 0) - return ret; - - Debug (15, "FDE covers IP 0x%lx-0x%lx, LSDA=0x%lx\n", - (long) pi->start_ip, (long) pi->end_ip, (long) pi->lsda); - - if (need_unwind_info) - { - pi->format = UNW_INFO_FORMAT_TABLE; - pi->unwind_info_size = sizeof (dci); - pi->unwind_info = mempool_alloc (&dwarf_cie_info_pool); - if (!pi->unwind_info) - return -UNW_ENOMEM; - - if (dci.have_abi_marker) - { - if ((ret = dwarf_readu16 (as, a, &addr, &dci.abi, arg)) < 0 - || (ret = dwarf_readu16 (as, a, &addr, &dci.tag, arg)) < 0) - return ret; - Debug (13, "Found ABI marker = (abi=%u, tag=%u)\n", - dci.abi, dci.tag); - } - - if (dci.sized_augmentation) - dci.fde_instr_start = aug_end_addr; - else - dci.fde_instr_start = addr; - dci.fde_instr_end = fde_end_addr; - - memcpy (pi->unwind_info, &dci, sizeof (dci)); - } - return 0; -} diff --git a/contrib/libunwind/src/dwarf/Gfind_proc_info-lsb.c b/contrib/libunwind/src/dwarf/Gfind_proc_info-lsb.c deleted file mode 100644 index d8cbc3e09bc..00000000000 --- a/contrib/libunwind/src/dwarf/Gfind_proc_info-lsb.c +++ /dev/null @@ -1,929 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Locate an FDE via the ELF data-structures defined by LSB v1.3 - (http://www.linuxbase.org/spec/). */ - -#include -#include -#include - -#include "dwarf_i.h" -#include "dwarf-eh.h" -#include "libunwind_i.h" - -struct table_entry - { - int32_t start_ip_offset; - int32_t fde_offset; - }; - -#ifndef UNW_REMOTE_ONLY - -#ifdef __linux -#include "os-linux.h" -#endif - -static int -linear_search (unw_addr_space_t as, unw_word_t ip, - unw_word_t eh_frame_start, unw_word_t eh_frame_end, - unw_word_t fde_count, - unw_proc_info_t *pi, int need_unwind_info, void *arg) -{ - unw_accessors_t *a = unw_get_accessors (unw_local_addr_space); - unw_word_t i = 0, fde_addr, addr = eh_frame_start; - int ret; - - while (i++ < fde_count && addr < eh_frame_end) - { - fde_addr = addr; - if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, - eh_frame_start, - 0, 0, arg)) < 0) - return ret; - - if (ip >= pi->start_ip && ip < pi->end_ip) - { - if (!need_unwind_info) - return 1; - addr = fde_addr; - if ((ret = dwarf_extract_proc_info_from_fde (as, a, &addr, pi, - eh_frame_start, - need_unwind_info, 0, - arg)) - < 0) - return ret; - return 1; - } - } - return -UNW_ENOINFO; -} -#endif /* !UNW_REMOTE_ONLY */ - -#ifdef CONFIG_DEBUG_FRAME -/* Load .debug_frame section from FILE. Allocates and returns space - in *BUF, and sets *BUFSIZE to its size. IS_LOCAL is 1 if using the - local process, in which case we can search the system debug file - directory; 0 for other address spaces, in which case we do - not. Returns 0 on success, 1 on error. Succeeds even if the file - contains no .debug_frame. */ -/* XXX: Could use mmap; but elf_map_image keeps tons mapped in. */ - -static int -load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) -{ - struct elf_image ei; - Elf_W (Shdr) *shdr; - int ret; - - ei.image = NULL; - - ret = elf_w (load_debuglink) (file, &ei, is_local); - if (ret != 0) - return ret; - - shdr = elf_w (find_section) (&ei, ".debug_frame"); - if (!shdr || - (shdr->sh_offset + shdr->sh_size > ei.size)) - { - munmap(ei.image, ei.size); - return 1; - } - - *bufsize = shdr->sh_size; - *buf = malloc (*bufsize); - - memcpy(*buf, shdr->sh_offset + ei.image, *bufsize); - - Debug (4, "read %zd bytes of .debug_frame from offset %zd\n", - *bufsize, shdr->sh_offset); - - munmap(ei.image, ei.size); - return 0; -} - -/* Locate the binary which originated the contents of address ADDR. Return - the name of the binary in *name (space is allocated by the caller) - Returns 0 if a binary is successfully found, or 1 if an error occurs. */ - -static int -find_binary_for_address (unw_word_t ip, char *name, size_t name_size) -{ -#if defined(__linux) && (!UNW_REMOTE_ONLY) - struct map_iterator mi; - int found = 0; - int pid = getpid (); - unsigned long segbase, mapoff, hi; - - if (maps_init (&mi, pid) != 0) - return 1; - - while (maps_next (&mi, &segbase, &hi, &mapoff)) - if (ip >= segbase && ip < hi) - { - size_t len = strlen (mi.path); - - if (len + 1 <= name_size) - { - memcpy (name, mi.path, len + 1); - found = 1; - } - break; - } - maps_close (&mi); - return !found; -#endif - - return 1; -} - -/* Locate and/or try to load a debug_frame section for address ADDR. Return - pointer to debug frame descriptor, or zero if not found. */ - -static struct unw_debug_frame_list * -locate_debug_info (unw_addr_space_t as, unw_word_t addr, const char *dlname, - unw_word_t start, unw_word_t end) -{ - struct unw_debug_frame_list *w, *fdesc = 0; - char path[PATH_MAX]; - char *name = path; - int err; - char *buf; - size_t bufsize; - - /* First, see if we loaded this frame already. */ - - for (w = as->debug_frames; w; w = w->next) - { - Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end); - if (addr >= w->start && addr < w->end) - return w; - } - - /* If the object name we receive is blank, there's still a chance of locating - the file by parsing /proc/self/maps. */ - - if (strcmp (dlname, "") == 0) - { - err = find_binary_for_address (addr, name, sizeof(path)); - if (err) - { - Debug (15, "tried to locate binary for 0x%" PRIx64 ", but no luck\n", - (uint64_t) addr); - return 0; - } - } - else - name = (char*) dlname; - - err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space); - - if (!err) - { - fdesc = malloc (sizeof (struct unw_debug_frame_list)); - - fdesc->start = start; - fdesc->end = end; - fdesc->debug_frame = buf; - fdesc->debug_frame_size = bufsize; - fdesc->index = NULL; - fdesc->next = as->debug_frames; - - as->debug_frames = fdesc; - } - - return fdesc; -} - -struct debug_frame_tab - { - struct table_entry *tab; - uint32_t length; - uint32_t size; - }; - -static void -debug_frame_tab_append (struct debug_frame_tab *tab, - unw_word_t fde_offset, unw_word_t start_ip) -{ - unsigned int length = tab->length; - - if (length == tab->size) - { - tab->size *= 2; - tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->size); - } - - tab->tab[length].fde_offset = fde_offset; - tab->tab[length].start_ip_offset = start_ip; - - tab->length = length + 1; -} - -static void -debug_frame_tab_shrink (struct debug_frame_tab *tab) -{ - if (tab->size > tab->length) - { - tab->tab = realloc (tab->tab, sizeof (struct table_entry) * tab->length); - tab->size = tab->length; - } -} - -static int -debug_frame_tab_compare (const void *a, const void *b) -{ - const struct table_entry *fa = a, *fb = b; - - if (fa->start_ip_offset > fb->start_ip_offset) - return 1; - else if (fa->start_ip_offset < fb->start_ip_offset) - return -1; - else - return 0; -} - -PROTECTED int -dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, unw_word_t ip, - unw_word_t segbase, const char* obj_name, - unw_word_t start, unw_word_t end) -{ - unw_dyn_info_t *di; - struct unw_debug_frame_list *fdesc = 0; - unw_accessors_t *a; - unw_word_t addr; - - Debug (15, "Trying to find .debug_frame for %s\n", obj_name); - di = di_debug; - - fdesc = locate_debug_info (unw_local_addr_space, ip, obj_name, start, end); - - if (!fdesc) - { - Debug (15, "couldn't load .debug_frame\n"); - return found; - } - else - { - char *buf; - size_t bufsize; - unw_word_t item_start, item_end = 0; - uint32_t u32val = 0; - uint64_t cie_id = 0; - struct debug_frame_tab tab; - - Debug (15, "loaded .debug_frame\n"); - - buf = fdesc->debug_frame; - bufsize = fdesc->debug_frame_size; - - if (bufsize == 0) - { - Debug (15, "zero-length .debug_frame\n"); - return found; - } - - /* Now create a binary-search table, if it does not already exist. */ - if (!fdesc->index) - { - addr = (unw_word_t) (uintptr_t) buf; - - a = unw_get_accessors (unw_local_addr_space); - - /* Find all FDE entries in debug_frame, and make into a sorted - index. */ - - tab.length = 0; - tab.size = 16; - tab.tab = calloc (tab.size, sizeof (struct table_entry)); - - while (addr < (unw_word_t) (uintptr_t) (buf + bufsize)) - { - uint64_t id_for_cie; - item_start = addr; - - dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL); - - if (u32val == 0) - break; - else if (u32val != 0xffffffff) - { - uint32_t cie_id32 = 0; - item_end = addr + u32val; - dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32, - NULL); - cie_id = cie_id32; - id_for_cie = 0xffffffff; - } - else - { - uint64_t u64val = 0; - /* Extended length. */ - dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL); - item_end = addr + u64val; - - dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL); - id_for_cie = 0xffffffffffffffffull; - } - - /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/ - - if (cie_id == id_for_cie) - ; - /*Debug (1, "Found CIE at %.8x.\n", item_start);*/ - else - { - unw_word_t fde_addr = item_start; - unw_proc_info_t this_pi; - int err; - - /*Debug (1, "Found FDE at %.8x\n", item_start);*/ - - err = dwarf_extract_proc_info_from_fde (unw_local_addr_space, - a, &fde_addr, - &this_pi, - (uintptr_t) buf, 0, 1, - NULL); - if (err == 0) - { - Debug (15, "start_ip = %lx, end_ip = %lx\n", - (long) this_pi.start_ip, (long) this_pi.end_ip); - debug_frame_tab_append (&tab, - item_start - (unw_word_t) (uintptr_t) buf, - this_pi.start_ip); - } - /*else - Debug (1, "FDE parse failed\n");*/ - } - - addr = item_end; - } - - debug_frame_tab_shrink (&tab); - qsort (tab.tab, tab.length, sizeof (struct table_entry), - debug_frame_tab_compare); - /* for (i = 0; i < tab.length; i++) - { - fprintf (stderr, "ip %x, fde offset %x\n", - (int) tab.tab[i].start_ip_offset, - (int) tab.tab[i].fde_offset); - }*/ - fdesc->index = tab.tab; - fdesc->index_size = tab.length; - } - - di->format = UNW_INFO_FORMAT_TABLE; - di->start_ip = fdesc->start; - di->end_ip = fdesc->end; - di->u.ti.name_ptr = (unw_word_t) (uintptr_t) obj_name; - di->u.ti.table_data = (unw_word_t *) fdesc; - di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t); - di->u.ti.segbase = segbase; - - found = 1; - Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, " - "gp=0x%lx, table_data=0x%lx\n", - (char *) (uintptr_t) di->u.ti.name_ptr, - (long) di->u.ti.segbase, (long) di->u.ti.table_len, - (long) di->gp, (long) di->u.ti.table_data); - } - return found; -} - -#endif /* CONFIG_DEBUG_FRAME */ - -#ifndef UNW_REMOTE_ONLY - -static Elf_W (Addr) -dwarf_find_eh_frame_section(struct dl_phdr_info *info) -{ - int rc; - struct elf_image ei; - Elf_W (Addr) eh_frame = 0; - Elf_W (Shdr)* shdr; - const char *file = info->dlpi_name; - char exepath[PATH_MAX]; - - if (strlen(file) == 0) - { - tdep_get_exe_image_path(exepath); - file = exepath; - } - - Debug (1, "looking for .eh_frame section in %s\n", - file); - - rc = elf_map_image (&ei, file); - if (rc != 0) - return 0; - - shdr = elf_w (find_section) (&ei, ".eh_frame"); - if (!shdr) - goto out; - - eh_frame = shdr->sh_addr + info->dlpi_addr; - Debug (4, "found .eh_frame at address %lx\n", - eh_frame); - -out: - munmap (ei.image, ei.size); - - return eh_frame; -} - -struct dwarf_callback_data - { - /* in: */ - unw_word_t ip; /* instruction-pointer we're looking for */ - unw_proc_info_t *pi; /* proc-info pointer */ - int need_unwind_info; - /* out: */ - int single_fde; /* did we find a single FDE? (vs. a table) */ - unw_dyn_info_t di; /* table info (if single_fde is false) */ - unw_dyn_info_t di_debug; /* additional table info for .debug_frame */ - }; - -/* ptr is a pointer to a dwarf_callback_data structure and, on entry, - member ip contains the instruction-pointer we're looking - for. */ -HIDDEN int -dwarf_callback (struct dl_phdr_info *info, size_t size, void *ptr) -{ - struct dwarf_callback_data *cb_data = ptr; - unw_dyn_info_t *di = &cb_data->di; - const Elf_W(Phdr) *phdr, *p_eh_hdr, *p_dynamic, *p_text; - unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, ip; - Elf_W(Addr) load_base, max_load_addr = 0; - int ret, need_unwind_info = cb_data->need_unwind_info; - unw_proc_info_t *pi = cb_data->pi; - struct dwarf_eh_frame_hdr *hdr = NULL; - unw_accessors_t *a; - long n; - int found = 0; - struct dwarf_eh_frame_hdr synth_eh_frame_hdr; -#ifdef CONFIG_DEBUG_FRAME - unw_word_t start, end; -#endif /* CONFIG_DEBUG_FRAME*/ - - ip = cb_data->ip; - - /* Make sure struct dl_phdr_info is at least as big as we need. */ - if (size < offsetof (struct dl_phdr_info, dlpi_phnum) - + sizeof (info->dlpi_phnum)) - return -1; - - Debug (15, "checking %s, base=0x%lx)\n", - info->dlpi_name, (long) info->dlpi_addr); - - phdr = info->dlpi_phdr; - load_base = info->dlpi_addr; - p_text = NULL; - p_eh_hdr = NULL; - p_dynamic = NULL; - - /* See if PC falls into one of the loaded segments. Find the - eh-header segment at the same time. */ - for (n = info->dlpi_phnum; --n >= 0; phdr++) - { - if (phdr->p_type == PT_LOAD) - { - Elf_W(Addr) vaddr = phdr->p_vaddr + load_base; - - if (ip >= vaddr && ip < vaddr + phdr->p_memsz) - p_text = phdr; - - if (vaddr + phdr->p_filesz > max_load_addr) - max_load_addr = vaddr + phdr->p_filesz; - } - else if (phdr->p_type == PT_GNU_EH_FRAME) - p_eh_hdr = phdr; - else if (phdr->p_type == PT_DYNAMIC) - p_dynamic = phdr; - } - - if (!p_text) - return 0; - - if (p_eh_hdr) - { - hdr = (struct dwarf_eh_frame_hdr *) (p_eh_hdr->p_vaddr + load_base); - } - else - { - Elf_W (Addr) eh_frame; - Debug (1, "no .eh_frame_hdr section found\n"); - eh_frame = dwarf_find_eh_frame_section (info); - if (eh_frame) - { - Debug (1, "using synthetic .eh_frame_hdr section for %s\n", - info->dlpi_name); - synth_eh_frame_hdr.version = DW_EH_VERSION; - synth_eh_frame_hdr.eh_frame_ptr_enc = DW_EH_PE_absptr | - ((sizeof(Elf_W (Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8); - synth_eh_frame_hdr.fde_count_enc = DW_EH_PE_omit; - synth_eh_frame_hdr.table_enc = DW_EH_PE_omit; - synth_eh_frame_hdr.eh_frame = eh_frame; - hdr = &synth_eh_frame_hdr; - } - } - - if (hdr) - { - if (p_dynamic) - { - /* For dynamicly linked executables and shared libraries, - DT_PLTGOT is the value that data-relative addresses are - relative to for that object. We call this the "gp". */ - Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(p_dynamic->p_vaddr + load_base); - for (; dyn->d_tag != DT_NULL; ++dyn) - if (dyn->d_tag == DT_PLTGOT) - { - /* Assume that _DYNAMIC is writable and GLIBC has - relocated it (true for x86 at least). */ - di->gp = dyn->d_un.d_ptr; - break; - } - } - else - /* Otherwise this is a static executable with no _DYNAMIC. Assume - that data-relative addresses are relative to 0, i.e., - absolute. */ - di->gp = 0; - pi->gp = di->gp; - - if (hdr->version != DW_EH_VERSION) - { - Debug (1, "table `%s' has unexpected version %d\n", - info->dlpi_name, hdr->version); - return 0; - } - - a = unw_get_accessors (unw_local_addr_space); - addr = (unw_word_t) (uintptr_t) (&hdr->eh_frame); - - /* (Optionally) read eh_frame_ptr: */ - if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a, - &addr, hdr->eh_frame_ptr_enc, pi, - &eh_frame_start, NULL)) < 0) - return ret; - - /* (Optionally) read fde_count: */ - if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a, - &addr, hdr->fde_count_enc, pi, - &fde_count, NULL)) < 0) - return ret; - - if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) - { - /* If there is no search table or it has an unsupported - encoding, fall back on linear search. */ - if (hdr->table_enc == DW_EH_PE_omit) - Debug (4, "table `%s' lacks search table; doing linear search\n", - info->dlpi_name); - else - Debug (4, "table `%s' has encoding 0x%x; doing linear search\n", - info->dlpi_name, hdr->table_enc); - - eh_frame_end = max_load_addr; /* XXX can we do better? */ - - if (hdr->fde_count_enc == DW_EH_PE_omit) - fde_count = ~0UL; - if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit) - abort (); - - Debug (1, "eh_frame_start = %lx eh_frame_end = %lx\n", - eh_frame_start, eh_frame_end); - - /* XXX we know how to build a local binary search table for - .debug_frame, so we could do that here too. */ - found = linear_search (unw_local_addr_space, ip, - eh_frame_start, eh_frame_end, fde_count, - pi, need_unwind_info, NULL); - if (found != 1) - found = 0; - else - cb_data->single_fde = 1; - } - else - { - di->format = UNW_INFO_FORMAT_REMOTE_TABLE; - di->start_ip = p_text->p_vaddr + load_base; - di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz; - di->u.rti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name; - di->u.rti.table_data = addr; - assert (sizeof (struct table_entry) % sizeof (unw_word_t) == 0); - di->u.rti.table_len = (fde_count * sizeof (struct table_entry) - / sizeof (unw_word_t)); - /* For the binary-search table in the eh_frame_hdr, data-relative - means relative to the start of that section... */ - di->u.rti.segbase = (unw_word_t) (uintptr_t) hdr; - - found = 1; - Debug (15, "found table `%s': segbase=0x%lx, len=%lu, gp=0x%lx, " - "table_data=0x%lx\n", (char *) (uintptr_t) di->u.rti.name_ptr, - (long) di->u.rti.segbase, (long) di->u.rti.table_len, - (long) di->gp, (long) di->u.rti.table_data); - } - } - -#ifdef CONFIG_DEBUG_FRAME - /* Find the start/end of the described region by parsing the phdr_info - structure. */ - start = (unw_word_t) -1; - end = 0; - - for (n = 0; n < info->dlpi_phnum; n++) - { - if (info->dlpi_phdr[n].p_type == PT_LOAD) - { - unw_word_t seg_start = info->dlpi_addr + info->dlpi_phdr[n].p_vaddr; - unw_word_t seg_end = seg_start + info->dlpi_phdr[n].p_memsz; - - if (seg_start < start) - start = seg_start; - - if (seg_end > end) - end = seg_end; - } - } - - found = dwarf_find_debug_frame (found, &cb_data->di_debug, ip, - info->dlpi_addr, info->dlpi_name, start, - end); -#endif /* CONFIG_DEBUG_FRAME */ - - return found; -} - -HIDDEN int -dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, int need_unwind_info, void *arg) -{ - struct dwarf_callback_data cb_data; - intrmask_t saved_mask; - int ret; - - Debug (14, "looking for IP=0x%lx\n", (long) ip); - - memset (&cb_data, 0, sizeof (cb_data)); - cb_data.ip = ip; - cb_data.pi = pi; - cb_data.need_unwind_info = need_unwind_info; - cb_data.di.format = -1; - cb_data.di_debug.format = -1; - - SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); - ret = dl_iterate_phdr (dwarf_callback, &cb_data); - SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); - - if (ret > 0) - { - if (cb_data.single_fde) - /* already got the result in *pi */ - return 0; - - /* search the table: */ - if (cb_data.di.format != -1) - ret = dwarf_search_unwind_table (as, ip, &cb_data.di, - pi, need_unwind_info, arg); - else - ret = -UNW_ENOINFO; - - if (ret == -UNW_ENOINFO && cb_data.di_debug.format != -1) - ret = dwarf_search_unwind_table (as, ip, &cb_data.di_debug, pi, - need_unwind_info, arg); - } - else - ret = -UNW_ENOINFO; - - return ret; -} - -static inline const struct table_entry * -lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip) -{ - unsigned long table_len = table_size / sizeof (struct table_entry); - const struct table_entry *e = NULL; - unsigned long lo, hi, mid; - - /* do a binary search for right entry: */ - for (lo = 0, hi = table_len; lo < hi;) - { - mid = (lo + hi) / 2; - e = table + mid; - Debug (15, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset); - if (rel_ip < e->start_ip_offset) - hi = mid; - else - lo = mid + 1; - } - if (hi <= 0) - return NULL; - e = table + hi - 1; - return e; -} - -#endif /* !UNW_REMOTE_ONLY */ - -#ifndef UNW_LOCAL_ONLY - -/* Lookup an unwind-table entry in remote memory. Returns 1 if an - entry is found, 0 if no entry is found, negative if an error - occurred reading remote memory. */ -static int -remote_lookup (unw_addr_space_t as, - unw_word_t table, size_t table_size, int32_t rel_ip, - struct table_entry *e, int32_t *last_ip_offset, void *arg) -{ - unsigned long table_len = table_size / sizeof (struct table_entry); - unw_accessors_t *a = unw_get_accessors (as); - unsigned long lo, hi, mid; - unw_word_t e_addr = 0; - int32_t start = 0; - int ret; - - /* do a binary search for right entry: */ - for (lo = 0, hi = table_len; lo < hi;) - { - mid = (lo + hi) / 2; - e_addr = table + mid * sizeof (struct table_entry); - if ((ret = dwarf_reads32 (as, a, &e_addr, &start, arg)) < 0) - return ret; - - if (rel_ip < start) - hi = mid; - else - lo = mid + 1; - } - if (hi <= 0) - return 0; - e_addr = table + (hi - 1) * sizeof (struct table_entry); - if ((ret = dwarf_reads32 (as, a, &e_addr, &e->start_ip_offset, arg)) < 0 - || (ret = dwarf_reads32 (as, a, &e_addr, &e->fde_offset, arg)) < 0 - || (hi < table_len && - (ret = dwarf_reads32 (as, a, &e_addr, last_ip_offset, arg)) < 0)) - return ret; - return 1; -} - -#endif /* !UNW_LOCAL_ONLY */ - -static int is_remote_table(int format) -{ - return (format == UNW_INFO_FORMAT_REMOTE_TABLE || - format == UNW_INFO_FORMAT_IP_OFFSET); -} - -PROTECTED int -dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - const struct table_entry *e = NULL, *table; - unw_word_t ip_base = 0, segbase = 0, last_ip, fde_addr; - unw_accessors_t *a; -#ifndef UNW_LOCAL_ONLY - struct table_entry ent; -#endif - int ret; - unw_word_t debug_frame_base; - size_t table_len; - -#ifdef UNW_REMOTE_ONLY - assert (is_remote_table(di->format)); -#else - assert (is_remote_table(di->format) - || di->format == UNW_INFO_FORMAT_TABLE); -#endif - assert (ip >= di->start_ip && ip < di->end_ip); - - if (is_remote_table(di->format)) - { - table = (const struct table_entry *) (uintptr_t) di->u.rti.table_data; - table_len = di->u.rti.table_len * sizeof (unw_word_t); - debug_frame_base = 0; - } - else - { - assert(di->format == UNW_INFO_FORMAT_TABLE); -#ifndef UNW_REMOTE_ONLY - struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data; - - /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address - space. Both the index and the unwind tables live in local memory, but - the address space to check for properties like the address size and - endianness is the target one. */ - as = unw_local_addr_space; - table = fdesc->index; - table_len = fdesc->index_size * sizeof (struct table_entry); - debug_frame_base = (uintptr_t) fdesc->debug_frame; -#endif - } - - a = unw_get_accessors (as); - - segbase = di->u.rti.segbase; - if (di->format == UNW_INFO_FORMAT_IP_OFFSET) { - ip_base = di->start_ip; - } else { - ip_base = segbase; - } - -#ifndef UNW_REMOTE_ONLY - if (as == unw_local_addr_space) - { - e = lookup (table, table_len, ip - ip_base); - if (e && &e[1] < &table[table_len]) - last_ip = e[1].start_ip_offset + ip_base; - else - last_ip = di->end_ip; - } - else -#endif - { -#ifndef UNW_LOCAL_ONLY - int32_t last_ip_offset = di->end_ip - ip_base; - segbase = di->u.rti.segbase; - if ((ret = remote_lookup (as, (uintptr_t) table, table_len, - ip - ip_base, &ent, &last_ip_offset, arg)) < 0) - return ret; - if (ret) - { - e = &ent; - last_ip = last_ip_offset + ip_base; - } - else - e = NULL; /* no info found */ -#endif - } - if (!e) - { - Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n", - (long) ip, (long) di->start_ip, (long) di->end_ip); - /* IP is inside this table's range, but there is no explicit - unwind info. */ - return -UNW_ENOINFO; - } - Debug (15, "ip=0x%lx, start_ip=0x%lx\n", - (long) ip, (long) (e->start_ip_offset)); - if (debug_frame_base) - fde_addr = e->fde_offset + debug_frame_base; - else - fde_addr = e->fde_offset + segbase; - Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, " - "fde_addr = %lx\n", (long) e->fde_offset, (long) segbase, - (long) debug_frame_base, (long) fde_addr); - if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi, - debug_frame_base ? - debug_frame_base : segbase, - need_unwind_info, - debug_frame_base != 0, arg)) < 0) - return ret; - - /* .debug_frame uses an absolute encoding that does not know about any - shared library relocation. */ - if (di->format == UNW_INFO_FORMAT_TABLE) - { - pi->start_ip += segbase; - pi->end_ip += segbase; - pi->flags = UNW_PI_FLAG_DEBUG_FRAME; - } - -#if defined(NEED_LAST_IP) - pi->last_ip = last_ip; -#else - (void)last_ip; -#endif - if (ip < pi->start_ip || ip >= pi->end_ip) - return -UNW_ENOINFO; - - return 0; -} - -HIDDEN void -dwarf_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg) -{ - return; /* always a nop */ -} diff --git a/contrib/libunwind/src/dwarf/Gfind_unwind_table.c b/contrib/libunwind/src/dwarf/Gfind_unwind_table.c deleted file mode 100644 index c171eeca9a9..00000000000 --- a/contrib/libunwind/src/dwarf/Gfind_unwind_table.c +++ /dev/null @@ -1,230 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include -#include - -#include - -#include "libunwind_i.h" -#include "dwarf-eh.h" -#include "dwarf_i.h" - -#define to_unw_word(p) ((unw_word_t) (uintptr_t) (p)) - -int -dwarf_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, - char *path, unw_word_t segbase, unw_word_t mapoff, - unw_word_t ip) -{ - Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL; - unw_word_t addr, eh_frame_start, fde_count, load_base; - unw_word_t max_load_addr = 0; - unw_word_t start_ip = to_unw_word (-1); - unw_word_t end_ip = 0; - struct dwarf_eh_frame_hdr *hdr; - unw_proc_info_t pi; - unw_accessors_t *a; - Elf_W(Ehdr) *ehdr; -#if UNW_TARGET_ARM - const Elf_W(Phdr) *parm_exidx = NULL; -#endif - int i, ret, found = 0; - - /* XXX: Much of this code is Linux/LSB-specific. */ - - if (!elf_w(valid_object) (&edi->ei)) - return -UNW_ENOINFO; - - ehdr = edi->ei.image; - phdr = (Elf_W(Phdr) *) ((char *) edi->ei.image + ehdr->e_phoff); - - for (i = 0; i < ehdr->e_phnum; ++i) - { - switch (phdr[i].p_type) - { - case PT_LOAD: - if (phdr[i].p_vaddr < start_ip) - start_ip = phdr[i].p_vaddr; - - if (phdr[i].p_vaddr + phdr[i].p_memsz > end_ip) - end_ip = phdr[i].p_vaddr + phdr[i].p_memsz; - - if (phdr[i].p_offset == mapoff) - ptxt = phdr + i; - if ((uintptr_t) edi->ei.image + phdr->p_filesz > max_load_addr) - max_load_addr = (uintptr_t) edi->ei.image + phdr->p_filesz; - break; - - case PT_GNU_EH_FRAME: - peh_hdr = phdr + i; - break; - - case PT_DYNAMIC: - pdyn = phdr + i; - break; - -#if UNW_TARGET_ARM - case PT_ARM_EXIDX: - parm_exidx = phdr + i; - break; -#endif - - default: - break; - } - } - - if (!ptxt) - return 0; - - load_base = segbase - ptxt->p_vaddr; - start_ip += load_base; - end_ip += load_base; - - if (peh_hdr) - { - if (pdyn) - { - /* For dynamicly linked executables and shared libraries, - DT_PLTGOT is the value that data-relative addresses are - relative to for that object. We call this the "gp". */ - Elf_W(Dyn) *dyn = (Elf_W(Dyn) *)(pdyn->p_offset - + (char *) edi->ei.image); - for (; dyn->d_tag != DT_NULL; ++dyn) - if (dyn->d_tag == DT_PLTGOT) - { - /* Assume that _DYNAMIC is writable and GLIBC has - relocated it (true for x86 at least). */ - edi->di_cache.gp = dyn->d_un.d_ptr; - break; - } - } - else - /* Otherwise this is a static executable with no _DYNAMIC. Assume - that data-relative addresses are relative to 0, i.e., - absolute. */ - edi->di_cache.gp = 0; - - hdr = (struct dwarf_eh_frame_hdr *) (peh_hdr->p_offset - + (char *) edi->ei.image); - if (hdr->version != DW_EH_VERSION) - { - Debug (1, "table `%s' has unexpected version %d\n", - path, hdr->version); - return -UNW_ENOINFO; - } - - a = unw_get_accessors (unw_local_addr_space); - addr = to_unw_word (&hdr->eh_frame); - - /* Fill in a dummy proc_info structure. We just need to fill in - enough to ensure that dwarf_read_encoded_pointer() can do it's - job. Since we don't have a procedure-context at this point, all - we have to do is fill in the global-pointer. */ - memset (&pi, 0, sizeof (pi)); - pi.gp = edi->di_cache.gp; - - /* (Optionally) read eh_frame_ptr: */ - if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a, - &addr, hdr->eh_frame_ptr_enc, &pi, - &eh_frame_start, NULL)) < 0) - return -UNW_ENOINFO; - - /* (Optionally) read fde_count: */ - if ((ret = dwarf_read_encoded_pointer (unw_local_addr_space, a, - &addr, hdr->fde_count_enc, &pi, - &fde_count, NULL)) < 0) - return -UNW_ENOINFO; - - if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) - { - #if 1 - abort (); - #else - unw_word_t eh_frame_end; - - /* If there is no search table or it has an unsupported - encoding, fall back on linear search. */ - if (hdr->table_enc == DW_EH_PE_omit) - Debug (4, "EH lacks search table; doing linear search\n"); - else - Debug (4, "EH table has encoding 0x%x; doing linear search\n", - hdr->table_enc); - - eh_frame_end = max_load_addr; /* XXX can we do better? */ - - if (hdr->fde_count_enc == DW_EH_PE_omit) - fde_count = ~0UL; - if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit) - abort (); - - return linear_search (unw_local_addr_space, ip, - eh_frame_start, eh_frame_end, fde_count, - pi, need_unwind_info, NULL); - #endif - } - - edi->di_cache.start_ip = start_ip; - edi->di_cache.end_ip = end_ip; - edi->di_cache.format = UNW_INFO_FORMAT_REMOTE_TABLE; - edi->di_cache.u.rti.name_ptr = 0; - /* two 32-bit values (ip_offset/fde_offset) per table-entry: */ - edi->di_cache.u.rti.table_len = (fde_count * 8) / sizeof (unw_word_t); - edi->di_cache.u.rti.table_data = ((load_base + peh_hdr->p_vaddr) - + (addr - to_unw_word (edi->ei.image) - - peh_hdr->p_offset)); - - /* For the binary-search table in the eh_frame_hdr, data-relative - means relative to the start of that section... */ - edi->di_cache.u.rti.segbase = ((load_base + peh_hdr->p_vaddr) - + (to_unw_word (hdr) - - to_unw_word (edi->ei.image) - - peh_hdr->p_offset)); - found = 1; - } - -#if UNW_TARGET_ARM - if (parm_exidx) - { - edi->di_arm.format = UNW_INFO_FORMAT_ARM_EXIDX; - edi->di_arm.start_ip = start_ip; - edi->di_arm.end_ip = end_ip; - edi->di_arm.u.rti.name_ptr = to_unw_word (path); - edi->di_arm.u.rti.table_data = load_base + parm_exidx->p_vaddr; - edi->di_arm.u.rti.table_len = parm_exidx->p_memsz; - found = 1; - } -#endif - -#ifdef CONFIG_DEBUG_FRAME - /* Try .debug_frame. */ - found = dwarf_find_debug_frame (found, &edi->di_debug, ip, load_base, path, - start_ip, end_ip); -#endif - - return found; -} diff --git a/contrib/libunwind/src/dwarf/Gparser.c b/contrib/libunwind/src/dwarf/Gparser.c deleted file mode 100644 index 9d405e76696..00000000000 --- a/contrib/libunwind/src/dwarf/Gparser.c +++ /dev/null @@ -1,1052 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "dwarf_i.h" -#include "libunwind_i.h" -#include -#include - -#define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool)) -#define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs)) - -#define DWARF_UNW_CACHE_SIZE(log_size) (1 << log_size) -#define DWARF_UNW_HASH_SIZE(log_size) (1 << (log_size + 1)) - -static inline int -read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - unw_word_t *valp, void *arg) -{ - int ret; - - if ((ret = dwarf_read_uleb128 (as, a, addr, valp, arg)) < 0) - return ret; - - if (*valp >= DWARF_NUM_PRESERVED_REGS) - { - Debug (1, "Invalid register number %u\n", (unsigned int) *valp); - return -UNW_EBADREG; - } - return 0; -} - -static inline void -set_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where, - unw_word_t val) -{ - sr->rs_current.reg.where[regnum] = where; - sr->rs_current.reg.val[regnum] = val; -} - -static inline int -push_rstate_stack(dwarf_stackable_reg_state_t **rs_stack) -{ - dwarf_stackable_reg_state_t *old_rs = *rs_stack; - if (NULL == (*rs_stack = alloc_reg_state ())) - { - *rs_stack = old_rs; - return -1; - } - (*rs_stack)->next = old_rs; - return 0; -} - -static inline void -pop_rstate_stack(dwarf_stackable_reg_state_t **rs_stack) -{ - dwarf_stackable_reg_state_t *old_rs = *rs_stack; - *rs_stack = old_rs->next; - free_reg_state (old_rs); -} - -static inline void -empty_rstate_stack(dwarf_stackable_reg_state_t **rs_stack) -{ - while (*rs_stack) - pop_rstate_stack(rs_stack); -} - -/* Run a CFI program to update the register state. */ -static int -run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr, - unw_word_t *ip, unw_word_t end_ip, - unw_word_t *addr, unw_word_t end_addr, - dwarf_stackable_reg_state_t **rs_stack, - struct dwarf_cie_info *dci) -{ - unw_addr_space_t as; - void *arg; - - if (c->pi.flags & UNW_PI_FLAG_DEBUG_FRAME) - { - /* .debug_frame CFI is stored in local address space. */ - as = unw_local_addr_space; - arg = NULL; - } - else - { - as = c->as; - arg = c->as_arg; - } - unw_accessors_t *a = unw_get_accessors (as); - int ret = 0; - - /* Process everything up to and including the current 'end_ip', - including all the DW_CFA_advance_loc instructions. See - 'c->use_prev_instr' use in 'fetch_proc_info' for details. */ - while (*ip <= end_ip && *addr < end_addr && ret >= 0) - { - unw_word_t operand = 0, regnum, val, len; - uint8_t u8, op; - uint16_t u16; - uint32_t u32; - - if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0) - break; - - if (op & DWARF_CFA_OPCODE_MASK) - { - operand = op & DWARF_CFA_OPERAND_MASK; - op &= ~DWARF_CFA_OPERAND_MASK; - } - switch ((dwarf_cfa_t) op) - { - case DW_CFA_advance_loc: - *ip += operand * dci->code_align; - Debug (15, "CFA_advance_loc to 0x%lx\n", (long) *ip); - break; - - case DW_CFA_advance_loc1: - if ((ret = dwarf_readu8 (as, a, addr, &u8, arg)) < 0) - break; - *ip += u8 * dci->code_align; - Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) *ip); - break; - - case DW_CFA_advance_loc2: - if ((ret = dwarf_readu16 (as, a, addr, &u16, arg)) < 0) - break; - *ip += u16 * dci->code_align; - Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) *ip); - break; - - case DW_CFA_advance_loc4: - if ((ret = dwarf_readu32 (as, a, addr, &u32, arg)) < 0) - break; - *ip += u32 * dci->code_align; - Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) *ip); - break; - - case DW_CFA_MIPS_advance_loc8: -#ifdef UNW_TARGET_MIPS - { - uint64_t u64 = 0; - - if ((ret = dwarf_readu64 (as, a, addr, &u64, arg)) < 0) - break; - *ip += u64 * dci->code_align; - Debug (15, "CFA_MIPS_advance_loc8\n"); - break; - } -#else - Debug (1, "DW_CFA_MIPS_advance_loc8 on non-MIPS target\n"); - ret = -UNW_EINVAL; - break; -#endif - - case DW_CFA_offset: - regnum = operand; - if (regnum >= DWARF_NUM_PRESERVED_REGS) - { - Debug (1, "Invalid register number %u in DW_cfa_OFFSET\n", - (unsigned int) regnum); - ret = -UNW_EBADREG; - break; - } - if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) - break; - set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); - Debug (15, "CFA_offset r%lu at cfa+0x%lx\n", - (long) regnum, (long) (val * dci->data_align)); - break; - - case DW_CFA_offset_extended: - if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) - || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) - break; - set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); - Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n", - (long) regnum, (long) (val * dci->data_align)); - break; - - case DW_CFA_offset_extended_sf: - if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) - || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)) - break; - set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); - Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n", - (long) regnum, (long) (val * dci->data_align)); - break; - - case DW_CFA_restore: - regnum = operand; - if (regnum >= DWARF_NUM_PRESERVED_REGS) - { - Debug (1, "Invalid register number %u in DW_CFA_restore\n", - (unsigned int) regnum); - ret = -UNW_EINVAL; - break; - } - sr->rs_current.reg.where[regnum] = sr->rs_initial.reg.where[regnum]; - sr->rs_current.reg.val[regnum] = sr->rs_initial.reg.val[regnum]; - Debug (15, "CFA_restore r%lu\n", (long) regnum); - break; - - case DW_CFA_restore_extended: - if ((ret = dwarf_read_uleb128 (as, a, addr, ®num, arg)) < 0) - break; - if (regnum >= DWARF_NUM_PRESERVED_REGS) - { - Debug (1, "Invalid register number %u in " - "DW_CFA_restore_extended\n", (unsigned int) regnum); - ret = -UNW_EINVAL; - break; - } - sr->rs_current.reg.where[regnum] = sr->rs_initial.reg.where[regnum]; - sr->rs_current.reg.val[regnum] = sr->rs_initial.reg.val[regnum]; - Debug (15, "CFA_restore_extended r%lu\n", (long) regnum); - break; - - case DW_CFA_nop: - break; - - case DW_CFA_set_loc: - if ((ret = dwarf_read_encoded_pointer (as, a, addr, dci->fde_encoding, - &c->pi, ip, - arg)) < 0) - break; - Debug (15, "CFA_set_loc to 0x%lx\n", (long) *ip); - break; - - case DW_CFA_undefined: - if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) - break; - set_reg (sr, regnum, DWARF_WHERE_UNDEF, 0); - Debug (15, "CFA_undefined r%lu\n", (long) regnum); - break; - - case DW_CFA_same_value: - if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) - break; - set_reg (sr, regnum, DWARF_WHERE_SAME, 0); - Debug (15, "CFA_same_value r%lu\n", (long) regnum); - break; - - case DW_CFA_register: - if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) - || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) - break; - set_reg (sr, regnum, DWARF_WHERE_REG, val); - Debug (15, "CFA_register r%lu to r%lu\n", (long) regnum, (long) val); - break; - - case DW_CFA_remember_state: - if (push_rstate_stack(rs_stack) < 0) - { - Debug (1, "Out of memory in DW_CFA_remember_state\n"); - ret = -UNW_ENOMEM; - break; - } - memcpy (&(*rs_stack)->state, &sr->rs_current, sizeof (sr->rs_current)); - Debug (15, "CFA_remember_state\n"); - break; - - case DW_CFA_restore_state: - if (!*rs_stack) - { - Debug (1, "register-state stack underflow\n"); - ret = -UNW_EINVAL; - break; - } - if (*ip < end_ip) { - memcpy (&sr->rs_current, &(*rs_stack)->state, sizeof (sr->rs_current)); - pop_rstate_stack(rs_stack); - } - Debug (15, "CFA_restore_state\n"); - break; - - case DW_CFA_def_cfa: - if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) - || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) - break; - set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); - set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */ - Debug (15, "CFA_def_cfa r%lu+0x%lx\n", (long) regnum, (long) val); - break; - - case DW_CFA_def_cfa_sf: - if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) - || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)) - break; - set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); - set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, - val * dci->data_align); /* factored! */ - Debug (15, "CFA_def_cfa_sf r%lu+0x%lx\n", - (long) regnum, (long) (val * dci->data_align)); - break; - - case DW_CFA_def_cfa_register: - if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) - break; - set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum); - Debug (15, "CFA_def_cfa_register r%lu\n", (long) regnum); - break; - - case DW_CFA_def_cfa_offset: - if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) - break; - set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */ - Debug (15, "CFA_def_cfa_offset 0x%lx\n", (long) val); - break; - - case DW_CFA_def_cfa_offset_sf: - if ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0) - break; - set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, - val * dci->data_align); /* factored! */ - Debug (15, "CFA_def_cfa_offset_sf 0x%lx\n", - (long) (val * dci->data_align)); - break; - - case DW_CFA_def_cfa_expression: - /* Save the address of the DW_FORM_block for later evaluation. */ - set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_EXPR, *addr); - - if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0) - break; - - Debug (15, "CFA_def_cfa_expr @ 0x%lx [%lu bytes]\n", - (long) *addr, (long) len); - *addr += len; - break; - - case DW_CFA_expression: - if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) - break; - - /* Save the address of the DW_FORM_block for later evaluation. */ - set_reg (sr, regnum, DWARF_WHERE_EXPR, *addr); - - if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0) - break; - - Debug (15, "CFA_expression r%lu @ 0x%lx [%lu bytes]\n", - (long) regnum, (long) addr, (long) len); - *addr += len; - break; - - case DW_CFA_val_expression: - if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0) - break; - - /* Save the address of the DW_FORM_block for later evaluation. */ - set_reg (sr, regnum, DWARF_WHERE_VAL_EXPR, *addr); - - if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0) - break; - - Debug (15, "CFA_val_expression r%lu @ 0x%lx [%lu bytes]\n", - (long) regnum, (long) addr, (long) len); - *addr += len; - break; - - case DW_CFA_GNU_args_size: - if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) - break; - if (*ip < end_ip) - { - sr->args_size = val; - Debug (15, "CFA_GNU_args_size %lu\n", (long) val); - } - break; - - case DW_CFA_GNU_negative_offset_extended: - /* A comment in GCC says that this is obsoleted by - DW_CFA_offset_extended_sf, but that it's used by older - PowerPC code. */ - if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) - || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) - break; - set_reg (sr, regnum, DWARF_WHERE_CFAREL, -(val * dci->data_align)); - Debug (15, "CFA_GNU_negative_offset_extended cfa+0x%lx\n", - (long) -(val * dci->data_align)); - break; - - case DW_CFA_GNU_window_save: -#ifdef UNW_TARGET_SPARC - /* This is a special CFA to handle all 16 windowed registers - on SPARC. */ - for (regnum = 16; regnum < 32; ++regnum) - set_reg (sr, regnum, DWARF_WHERE_CFAREL, - (regnum - 16) * sizeof (unw_word_t)); - Debug (15, "CFA_GNU_window_save\n"); - break; -#else - /* FALL THROUGH */ -#endif - case DW_CFA_lo_user: - case DW_CFA_hi_user: - Debug (1, "Unexpected CFA opcode 0x%x\n", op); - ret = -UNW_EINVAL; - break; - } - } - - if (ret > 0) - ret = 0; - return ret; -} - -static int -fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info) -{ - int ret, dynamic = 1; - - /* The 'ip' can point either to the previous or next instruction - depending on what type of frame we have: normal call or a place - to resume execution (e.g. after signal frame). - - For a normal call frame we need to back up so we point within the - call itself; this is important because a) the call might be the - very last instruction of the function and the edge of the FDE, - and b) so that run_cfi_program() runs locations up to the call - but not more. - - For execution resume, we need to do the exact opposite and look - up using the current 'ip' value. That is where execution will - continue, and it's important we get this right, as 'ip' could be - right at the function entry and hence FDE edge, or at instruction - that manipulates CFA (push/pop). */ - if (c->use_prev_instr) - --ip; - - memset (&c->pi, 0, sizeof (c->pi)); - - /* check dynamic info first --- it overrides everything else */ - ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, 1, - c->as_arg); - if (ret == -UNW_ENOINFO) - { - dynamic = 0; - if ((ret = tdep_find_proc_info (c, ip, 1)) < 0) - return ret; - } - - if (c->pi.format != UNW_INFO_FORMAT_DYNAMIC - && c->pi.format != UNW_INFO_FORMAT_TABLE - && c->pi.format != UNW_INFO_FORMAT_REMOTE_TABLE) - return -UNW_ENOINFO; - - c->pi_valid = 1; - c->pi_is_dynamic = dynamic; - - /* Let system/machine-dependent code determine frame-specific attributes. */ - if (ret >= 0) - tdep_fetch_frame (c, ip, 1); - - /* Update use_prev_instr for the next frame. */ - if (need_unwind_info) - { - assert(c->pi.unwind_info); - struct dwarf_cie_info *dci = c->pi.unwind_info; - c->use_prev_instr = ! dci->signal_frame; - } - - return ret; -} - -static int -parse_dynamic (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr) -{ - Debug (1, "Not yet implemented\n"); - return -UNW_ENOINFO; -} - -static inline void -put_unwind_info (struct dwarf_cursor *c, unw_proc_info_t *pi) -{ - if (c->pi_is_dynamic) - unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg); - else if (pi->unwind_info && pi->format == UNW_INFO_FORMAT_TABLE) - { - mempool_free (&dwarf_cie_info_pool, pi->unwind_info); - pi->unwind_info = NULL; - } - c->pi_valid = 0; -} - -static inline int -setup_fde (struct dwarf_cursor *c, dwarf_state_record_t *sr) -{ - int i, ret; - - assert (c->pi_valid); - - memset (sr, 0, sizeof (*sr)); - for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i) - set_reg (sr, i, DWARF_WHERE_SAME, 0); - - struct dwarf_cie_info *dci = c->pi.unwind_info; - sr->rs_current.ret_addr_column = dci->ret_addr_column; - unw_word_t addr = dci->cie_instr_start; - unw_word_t curr_ip = 0; - dwarf_stackable_reg_state_t *rs_stack = NULL; - ret = run_cfi_program (c, sr, &curr_ip, ~(unw_word_t) 0, &addr, - dci->cie_instr_end, - &rs_stack, dci); - empty_rstate_stack(&rs_stack); - if (ret < 0) - return ret; - - memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial)); - return 0; -} - -static inline int -parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr) -{ - int ret; - struct dwarf_cie_info *dci = c->pi.unwind_info; - unw_word_t addr = dci->fde_instr_start; - unw_word_t curr_ip = c->pi.start_ip; - dwarf_stackable_reg_state_t *rs_stack = NULL; - ret = run_cfi_program (c, sr, &curr_ip, ip, &addr, dci->fde_instr_end, - &rs_stack, dci); - empty_rstate_stack(&rs_stack); - if (ret < 0) - return ret; - - return 0; -} - -HIDDEN int -dwarf_flush_rs_cache (struct dwarf_rs_cache *cache) -{ - int i; - - if (cache->log_size == DWARF_DEFAULT_LOG_UNW_CACHE_SIZE - || !cache->hash) { - cache->hash = cache->default_hash; - cache->buckets = cache->default_buckets; - cache->links = cache->default_links; - cache->log_size = DWARF_DEFAULT_LOG_UNW_CACHE_SIZE; - } else { - if (cache->hash && cache->hash != cache->default_hash) - munmap(cache->hash, DWARF_UNW_HASH_SIZE(cache->prev_log_size) - * sizeof (cache->hash[0])); - if (cache->buckets && cache->buckets != cache->default_buckets) - munmap(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->prev_log_size) - * sizeof (cache->buckets[0])); - if (cache->links && cache->links != cache->default_links) - munmap(cache->links, DWARF_UNW_CACHE_SIZE(cache->prev_log_size) - * sizeof (cache->links[0])); - GET_MEMORY(cache->hash, DWARF_UNW_HASH_SIZE(cache->log_size) - * sizeof (cache->hash[0])); - GET_MEMORY(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->log_size) - * sizeof (cache->buckets[0])); - GET_MEMORY(cache->links, DWARF_UNW_CACHE_SIZE(cache->log_size) - * sizeof (cache->links[0])); - if (!cache->hash || !cache->buckets || !cache->links) - { - Debug (1, "Unable to allocate cache memory"); - return -UNW_ENOMEM; - } - cache->prev_log_size = cache->log_size; - } - - cache->rr_head = 0; - - for (i = 0; i < DWARF_UNW_CACHE_SIZE(cache->log_size); ++i) - { - cache->links[i].coll_chain = -1; - cache->links[i].ip = 0; - cache->links[i].valid = 0; - } - for (i = 0; i< DWARF_UNW_HASH_SIZE(cache->log_size); ++i) - cache->hash[i] = -1; - - return 0; -} - -static inline struct dwarf_rs_cache * -get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp) -{ - struct dwarf_rs_cache *cache = &as->global_cache; - unw_caching_policy_t caching = as->caching_policy; - - if (caching == UNW_CACHE_NONE) - return NULL; - -#if defined(HAVE___THREAD) && HAVE___THREAD - if (likely (caching == UNW_CACHE_PER_THREAD)) - { - static __thread struct dwarf_rs_cache tls_cache __attribute__((tls_model("initial-exec"))); - Debug (16, "using TLS cache\n"); - cache = &tls_cache; - } - else -#else - if (likely (caching == UNW_CACHE_GLOBAL)) -#endif - { - Debug (16, "acquiring lock\n"); - lock_acquire (&cache->lock, *saved_maskp); - } - - if ((atomic_read (&as->cache_generation) != atomic_read (&cache->generation)) - || !cache->hash) - { - /* cache_size is only set in the global_cache, copy it over before flushing */ - cache->log_size = as->global_cache.log_size; - if (dwarf_flush_rs_cache (cache) < 0) - return NULL; - cache->generation = as->cache_generation; - } - - return cache; -} - -static inline void -put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache, - intrmask_t *saved_maskp) -{ - assert (as->caching_policy != UNW_CACHE_NONE); - - Debug (16, "unmasking signals/interrupts and releasing lock\n"); - if (likely (as->caching_policy == UNW_CACHE_GLOBAL)) - lock_release (&cache->lock, *saved_maskp); -} - -static inline unw_hash_index_t CONST_ATTR -hash (unw_word_t ip, unsigned short log_size) -{ - /* based on (sqrt(5)/2-1)*2^64 */ -# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL) - - return ip * magic >> ((sizeof(unw_word_t) * 8) - (log_size + 1)); -} - -static inline long -cache_match (struct dwarf_rs_cache *cache, unsigned short index, unw_word_t ip) -{ - return (cache->links[index].valid && (ip == cache->links[index].ip)); -} - -static dwarf_reg_state_t * -rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c) -{ - unsigned short index; - unw_word_t ip = c->ip; - - if (c->hint > 0) - { - index = c->hint - 1; - if (cache_match (cache, index, ip)) - return &cache->buckets[index]; - } - - for (index = cache->hash[hash (ip, cache->log_size)]; - index < DWARF_UNW_CACHE_SIZE(cache->log_size); - index = cache->links[index].coll_chain) - { - if (cache_match (cache, index, ip)) - return &cache->buckets[index]; - } - return NULL; -} - -static inline dwarf_reg_state_t * -rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c) -{ - unw_hash_index_t index; - unsigned short head; - - head = cache->rr_head; - cache->rr_head = (head + 1) & (DWARF_UNW_CACHE_SIZE(cache->log_size) - 1); - - /* remove the old rs from the hash table (if it's there): */ - if (cache->links[head].ip) - { - unsigned short *pindex; - for (pindex = &cache->hash[hash (cache->links[head].ip, cache->log_size)]; - *pindex < DWARF_UNW_CACHE_SIZE(cache->log_size); - pindex = &cache->links[*pindex].coll_chain) - { - if (*pindex == head) - { - *pindex = cache->links[*pindex].coll_chain; - break; - } - } - } - - /* enter new rs in the hash table */ - index = hash (c->ip, cache->log_size); - cache->links[head].coll_chain = cache->hash[index]; - cache->hash[index] = head; - - cache->links[head].ip = c->ip; - cache->links[head].valid = 1; - cache->links[head].signal_frame = tdep_cache_frame(c); - return cache->buckets + head; -} - -static int -create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr, - unw_word_t ip) -{ - int ret; - switch (c->pi.format) - { - case UNW_INFO_FORMAT_TABLE: - case UNW_INFO_FORMAT_REMOTE_TABLE: - if ((ret = setup_fde(c, sr)) < 0) - return ret; - ret = parse_fde (c, ip, sr); - break; - - case UNW_INFO_FORMAT_DYNAMIC: - ret = parse_dynamic (c, ip, sr); - break; - - default: - Debug (1, "Unexpected unwind-info format %d\n", c->pi.format); - ret = -UNW_EINVAL; - } - return ret; -} - -static inline int -eval_location_expr (struct dwarf_cursor *c, unw_addr_space_t as, - unw_accessors_t *a, unw_word_t addr, - dwarf_loc_t *locp, void *arg) -{ - int ret, is_register; - unw_word_t len, val; - - /* read the length of the expression: */ - if ((ret = dwarf_read_uleb128 (as, a, &addr, &len, arg)) < 0) - return ret; - - /* evaluate the expression: */ - if ((ret = dwarf_eval_expr (c, &addr, len, &val, &is_register)) < 0) - return ret; - - if (is_register) - *locp = DWARF_REG_LOC (c, dwarf_to_unw_regnum (val)); - else - *locp = DWARF_MEM_LOC (c, val); - - return 0; -} - -static int -apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) -{ - unw_word_t regnum, addr, cfa, ip; - unw_word_t prev_ip, prev_cfa; - unw_addr_space_t as; - dwarf_loc_t cfa_loc; - unw_accessors_t *a; - int i, ret; - void *arg; - - prev_ip = c->ip; - prev_cfa = c->cfa; - - as = c->as; - arg = c->as_arg; - a = unw_get_accessors (as); - - /* Evaluate the CFA first, because it may be referred to by other - expressions. */ - - if (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG) - { - /* CFA is equal to [reg] + offset: */ - - /* As a special-case, if the stack-pointer is the CFA and the - stack-pointer wasn't saved, popping the CFA implicitly pops - the stack-pointer as well. */ - if ((rs->reg.val[DWARF_CFA_REG_COLUMN] == UNW_TDEP_SP) - && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg.val)) - && (rs->reg.where[UNW_TDEP_SP] == DWARF_WHERE_SAME)) - cfa = c->cfa; - else - { - regnum = dwarf_to_unw_regnum (rs->reg.val[DWARF_CFA_REG_COLUMN]); - if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0) - return ret; - } - cfa += rs->reg.val[DWARF_CFA_OFF_COLUMN]; - } - else - { - /* CFA is equal to EXPR: */ - - assert (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_EXPR); - - addr = rs->reg.val[DWARF_CFA_REG_COLUMN]; - if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0) - return ret; - /* the returned location better be a memory location... */ - if (DWARF_IS_REG_LOC (cfa_loc)) - return -UNW_EBADFRAME; - cfa = DWARF_GET_LOC (cfa_loc); - } - - for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) - { - switch ((dwarf_where_t) rs->reg.where[i]) - { - case DWARF_WHERE_UNDEF: - c->loc[i] = DWARF_NULL_LOC; - break; - - case DWARF_WHERE_SAME: - break; - - case DWARF_WHERE_CFAREL: - c->loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg.val[i]); - break; - - case DWARF_WHERE_REG: - c->loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg.val[i])); - break; - - case DWARF_WHERE_EXPR: - addr = rs->reg.val[i]; - if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0) - return ret; - break; - - case DWARF_WHERE_VAL_EXPR: - addr = rs->reg.val[i]; - if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0) - return ret; - c->loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (c->loc[i])); - break; - } - } - - c->cfa = cfa; - /* DWARF spec says undefined return address location means end of stack. */ - if (DWARF_IS_NULL_LOC (c->loc[rs->ret_addr_column])) - { - c->ip = 0; - ret = 0; - } - else - { - ret = dwarf_get (c, c->loc[rs->ret_addr_column], &ip); - if (ret < 0) - return ret; - c->ip = ip; - ret = 1; - } - - /* XXX: check for ip to be code_aligned */ - if (c->ip == prev_ip && c->cfa == prev_cfa) - { - Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", - __FUNCTION__, (long) c->ip); - return -UNW_EBADFRAME; - } - - if (c->stash_frames) - tdep_stash_frame (c, rs); - - return ret; -} - -/* Find the saved locations. */ -static int -find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr) -{ - dwarf_reg_state_t *rs; - struct dwarf_rs_cache *cache; - int ret = 0; - intrmask_t saved_mask; - - if ((cache = get_rs_cache(c->as, &saved_mask)) && - (rs = rs_lookup(cache, c))) - { - /* update hint; no locking needed: single-word writes are atomic */ - unsigned short index = rs - cache->buckets; - c->use_prev_instr = ! cache->links[index].signal_frame; - memcpy (&sr->rs_current, rs, sizeof (*rs)); - } - else - { - ret = fetch_proc_info (c, c->ip, 1); - if (ret >= 0) - ret = create_state_record_for (c, sr, c->ip); - put_unwind_info (c, &c->pi); - - if (cache && ret >= 0) - { - rs = rs_new (cache, c); - cache->links[rs - cache->buckets].hint = 0; - memcpy(rs, &sr->rs_current, sizeof(*rs)); - } - } - - unsigned short index = -1; - if (cache) - { - put_rs_cache (c->as, cache, &saved_mask); - if (rs) - { - index = rs - cache->buckets; - c->hint = cache->links[index].hint; - cache->links[c->prev_rs].hint = index + 1; - c->prev_rs = index; - } - } - if (ret < 0) - return ret; - if (cache) - tdep_reuse_frame (c, cache->links[index].signal_frame); - return 0; -} - -/* The function finds the saved locations and applies the register - state as well. */ -HIDDEN int -dwarf_step (struct dwarf_cursor *c) -{ - int ret; - dwarf_state_record_t sr; - if ((ret = find_reg_state (c, &sr)) < 0) - return ret; - return apply_reg_state (c, &sr.rs_current); -} - -HIDDEN int -dwarf_make_proc_info (struct dwarf_cursor *c) -{ -#if 0 - if (c->as->caching_policy == UNW_CACHE_NONE - || get_cached_proc_info (c) < 0) -#endif - /* Need to check if current frame contains - args_size, and set cursor appropriately. Only - needed for unw_resume */ - dwarf_state_record_t sr; - int ret; - - /* Lookup it up the slow way... */ - ret = fetch_proc_info (c, c->ip, 0); - if (ret >= 0) - ret = create_state_record_for (c, &sr, c->ip); - put_unwind_info (c, &c->pi); - if (ret < 0) - return ret; - c->args_size = sr.args_size; - - return 0; -} - -static int -dwarf_reg_states_dynamic_iterate(struct dwarf_cursor *c, - unw_reg_states_callback cb, - void *token) -{ - Debug (1, "Not yet implemented\n"); - return -UNW_ENOINFO; -} - -static int -dwarf_reg_states_table_iterate(struct dwarf_cursor *c, - unw_reg_states_callback cb, - void *token) -{ - dwarf_state_record_t sr; - int ret = setup_fde(c, &sr); - struct dwarf_cie_info *dci = c->pi.unwind_info; - unw_word_t addr = dci->fde_instr_start; - unw_word_t curr_ip = c->pi.start_ip; - dwarf_stackable_reg_state_t *rs_stack = NULL; - while (ret >= 0 && curr_ip < c->pi.end_ip && addr < dci->fde_instr_end) - { - unw_word_t prev_ip = curr_ip; - ret = run_cfi_program (c, &sr, &curr_ip, prev_ip, &addr, dci->fde_instr_end, - &rs_stack, dci); - if (ret >= 0 && prev_ip < curr_ip) - ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), prev_ip, curr_ip); - } - empty_rstate_stack(&rs_stack); -#if defined(NEED_LAST_IP) - if (ret >= 0 && curr_ip < c->pi.last_ip) - /* report the dead zone after the procedure ends */ - ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.last_ip); -#else - if (ret >= 0 && curr_ip < c->pi.end_ip) - /* report for whatever is left before procedure end */ - ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.end_ip); -#endif - return ret; -} - -HIDDEN int -dwarf_reg_states_iterate(struct dwarf_cursor *c, - unw_reg_states_callback cb, - void *token) -{ - int ret = fetch_proc_info (c, c->ip, 1); - if (ret >= 0) - switch (c->pi.format) - { - case UNW_INFO_FORMAT_TABLE: - case UNW_INFO_FORMAT_REMOTE_TABLE: - ret = dwarf_reg_states_table_iterate(c, cb, token); - break; - - case UNW_INFO_FORMAT_DYNAMIC: - ret = dwarf_reg_states_dynamic_iterate (c, cb, token); - break; - - default: - Debug (1, "Unexpected unwind-info format %d\n", c->pi.format); - ret = -UNW_EINVAL; - } - put_unwind_info (c, &c->pi); - return ret; -} - -HIDDEN int -dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) -{ - return apply_reg_state(c, rs); -} diff --git a/contrib/libunwind/src/dwarf/Gpe.c b/contrib/libunwind/src/dwarf/Gpe.c deleted file mode 100644 index a0e37ba2329..00000000000 --- a/contrib/libunwind/src/dwarf/Gpe.c +++ /dev/null @@ -1,39 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "dwarf_i.h" -#include "libunwind_i.h" - -#include - -HIDDEN int -dwarf_read_encoded_pointer (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, unsigned char encoding, - const unw_proc_info_t *pi, - unw_word_t *valp, void *arg) -{ - return dwarf_read_encoded_pointer_inlined (as, a, addr, encoding, - pi, valp, arg); -} diff --git a/contrib/libunwind/src/dwarf/Lexpr.c b/contrib/libunwind/src/dwarf/Lexpr.c deleted file mode 100644 index 245970c9e3f..00000000000 --- a/contrib/libunwind/src/dwarf/Lexpr.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gexpr.c" -#endif diff --git a/contrib/libunwind/src/dwarf/Lfde.c b/contrib/libunwind/src/dwarf/Lfde.c deleted file mode 100644 index e779e8f192e..00000000000 --- a/contrib/libunwind/src/dwarf/Lfde.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gfde.c" -#endif diff --git a/contrib/libunwind/src/dwarf/Lfind_proc_info-lsb.c b/contrib/libunwind/src/dwarf/Lfind_proc_info-lsb.c deleted file mode 100644 index 27a5eeac188..00000000000 --- a/contrib/libunwind/src/dwarf/Lfind_proc_info-lsb.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gfind_proc_info-lsb.c" -#endif diff --git a/contrib/libunwind/src/dwarf/Lfind_unwind_table.c b/contrib/libunwind/src/dwarf/Lfind_unwind_table.c deleted file mode 100644 index 68e269f1d7f..00000000000 --- a/contrib/libunwind/src/dwarf/Lfind_unwind_table.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gfind_unwind_table.c" -#endif diff --git a/contrib/libunwind/src/dwarf/Lparser.c b/contrib/libunwind/src/dwarf/Lparser.c deleted file mode 100644 index f23aaf48e9c..00000000000 --- a/contrib/libunwind/src/dwarf/Lparser.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gparser.c" -#endif diff --git a/contrib/libunwind/src/dwarf/Lpe.c b/contrib/libunwind/src/dwarf/Lpe.c deleted file mode 100644 index a672358f063..00000000000 --- a/contrib/libunwind/src/dwarf/Lpe.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gpe.c" -#endif diff --git a/contrib/libunwind/src/dwarf/global.c b/contrib/libunwind/src/dwarf/global.c deleted file mode 100644 index 70985071425..00000000000 --- a/contrib/libunwind/src/dwarf/global.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "dwarf_i.h" - -HIDDEN struct mempool dwarf_reg_state_pool; -HIDDEN struct mempool dwarf_cie_info_pool; - -HIDDEN int -dwarf_init (void) -{ - mempool_init (&dwarf_reg_state_pool, sizeof (dwarf_stackable_reg_state_t), 0); - mempool_init (&dwarf_cie_info_pool, sizeof (struct dwarf_cie_info), 0); - return 0; -} diff --git a/contrib/libunwind/src/elf32.c b/contrib/libunwind/src/elf32.c deleted file mode 100644 index a70bb58f24d..00000000000 --- a/contrib/libunwind/src/elf32.c +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef UNW_REMOTE_ONLY -# include "elf32.h" -# include "elfxx.c" -#endif diff --git a/contrib/libunwind/src/elf32.h b/contrib/libunwind/src/elf32.h deleted file mode 100644 index 2c7bca4c9dc..00000000000 --- a/contrib/libunwind/src/elf32.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef elf32_h -#define elf32_h - -#ifndef ELF_CLASS -#define ELF_CLASS ELFCLASS32 -#endif -#include "elfxx.h" - -#endif /* elf32_h */ diff --git a/contrib/libunwind/src/elf64.c b/contrib/libunwind/src/elf64.c deleted file mode 100644 index 195b8879486..00000000000 --- a/contrib/libunwind/src/elf64.c +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef UNW_REMOTE_ONLY -# include "elf64.h" -# include "elfxx.c" -#endif diff --git a/contrib/libunwind/src/elf64.h b/contrib/libunwind/src/elf64.h deleted file mode 100644 index 091fba8e1f8..00000000000 --- a/contrib/libunwind/src/elf64.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef elf64_h -#define elf64_h - -#ifndef ELF_CLASS -#define ELF_CLASS ELFCLASS64 -#endif -#include "elfxx.h" - -#endif /* elf64_h */ diff --git a/contrib/libunwind/src/elfxx.c b/contrib/libunwind/src/elfxx.c deleted file mode 100644 index 48a08cdc383..00000000000 --- a/contrib/libunwind/src/elfxx.c +++ /dev/null @@ -1,478 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2005 Hewlett-Packard Co - Copyright (C) 2007 David Mosberger-Tang - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -#include -#include - -#ifdef HAVE_LZMA -#include -#endif /* HAVE_LZMA */ - -static Elf_W (Shdr)* -elf_w (section_table) (struct elf_image *ei) -{ - Elf_W (Ehdr) *ehdr = ei->image; - Elf_W (Off) soff; - - soff = ehdr->e_shoff; - if (soff + ehdr->e_shnum * ehdr->e_shentsize > ei->size) - { - Debug (1, "section table outside of image? (%lu > %lu)\n", - (unsigned long) (soff + ehdr->e_shnum * ehdr->e_shentsize), - (unsigned long) ei->size); - return NULL; - } - - return (Elf_W (Shdr) *) ((char *) ei->image + soff); -} - -static char* -elf_w (string_table) (struct elf_image *ei, int section) -{ - Elf_W (Ehdr) *ehdr = ei->image; - Elf_W (Off) soff, str_soff; - Elf_W (Shdr) *str_shdr; - - /* this offset is assumed to be OK */ - soff = ehdr->e_shoff; - - str_soff = soff + (section * ehdr->e_shentsize); - if (str_soff + ehdr->e_shentsize > ei->size) - { - Debug (1, "string shdr table outside of image? (%lu > %lu)\n", - (unsigned long) (str_soff + ehdr->e_shentsize), - (unsigned long) ei->size); - return NULL; - } - str_shdr = (Elf_W (Shdr) *) ((char *) ei->image + str_soff); - - if (str_shdr->sh_offset + str_shdr->sh_size > ei->size) - { - Debug (1, "string table outside of image? (%lu > %lu)\n", - (unsigned long) (str_shdr->sh_offset + str_shdr->sh_size), - (unsigned long) ei->size); - return NULL; - } - - Debug (16, "strtab=0x%lx\n", (long) str_shdr->sh_offset); - return ei->image + str_shdr->sh_offset; -} - -static int -elf_w (lookup_symbol) (unw_addr_space_t as, - unw_word_t ip, struct elf_image *ei, - Elf_W (Addr) load_offset, - char *buf, size_t buf_len, Elf_W (Addr) *min_dist) -{ - size_t syment_size; - Elf_W (Ehdr) *ehdr = ei->image; - Elf_W (Sym) *sym, *symtab, *symtab_end; - Elf_W (Shdr) *shdr; - Elf_W (Addr) val; - int i, ret = -UNW_ENOINFO; - char *strtab; - - if (!elf_w (valid_object) (ei)) - return -UNW_ENOINFO; - - shdr = elf_w (section_table) (ei); - if (!shdr) - return -UNW_ENOINFO; - - for (i = 0; i < ehdr->e_shnum; ++i) - { - switch (shdr->sh_type) - { - case SHT_SYMTAB: - case SHT_DYNSYM: - symtab = (Elf_W (Sym) *) ((char *) ei->image + shdr->sh_offset); - symtab_end = (Elf_W (Sym) *) ((char *) symtab + shdr->sh_size); - syment_size = shdr->sh_entsize; - - strtab = elf_w (string_table) (ei, shdr->sh_link); - if (!strtab) - break; - - Debug (16, "symtab=0x%lx[%d]\n", - (long) shdr->sh_offset, shdr->sh_type); - - for (sym = symtab; - sym < symtab_end; - sym = (Elf_W (Sym) *) ((char *) sym + syment_size)) - { - if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC - && sym->st_shndx != SHN_UNDEF) - { - val = sym->st_value; - if (sym->st_shndx != SHN_ABS) - val += load_offset; - if (tdep_get_func_addr (as, val, &val) < 0) - continue; - Debug (16, "0x%016lx info=0x%02x %s\n", - (long) val, sym->st_info, strtab + sym->st_name); - - if ((Elf_W (Addr)) (ip - val) < *min_dist) - { - *min_dist = (Elf_W (Addr)) (ip - val); - strncpy (buf, strtab + sym->st_name, buf_len); - buf[buf_len - 1] = '\0'; - ret = (strlen (strtab + sym->st_name) >= buf_len - ? -UNW_ENOMEM : 0); - } - } - } - break; - - default: - break; - } - shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize); - } - return ret; -} - -static Elf_W (Addr) -elf_w (get_load_offset) (struct elf_image *ei, unsigned long segbase, - unsigned long mapoff) -{ - Elf_W (Addr) offset = 0; - Elf_W (Ehdr) *ehdr; - Elf_W (Phdr) *phdr; - int i; - - ehdr = ei->image; - phdr = (Elf_W (Phdr) *) ((char *) ei->image + ehdr->e_phoff); - - for (i = 0; i < ehdr->e_phnum; ++i) - if (phdr[i].p_type == PT_LOAD && phdr[i].p_offset == mapoff) - { - offset = segbase - phdr[i].p_vaddr; - break; - } - - return offset; -} - -#if HAVE_LZMA -static size_t -xz_uncompressed_size (uint8_t *compressed, size_t length) -{ - uint64_t memlimit = UINT64_MAX; - size_t ret = 0, pos = 0; - lzma_stream_flags options; - lzma_index *index; - - if (length < LZMA_STREAM_HEADER_SIZE) - return 0; - - uint8_t *footer = compressed + length - LZMA_STREAM_HEADER_SIZE; - if (lzma_stream_footer_decode (&options, footer) != LZMA_OK) - return 0; - - if (length < LZMA_STREAM_HEADER_SIZE + options.backward_size) - return 0; - - uint8_t *indexdata = footer - options.backward_size; - if (lzma_index_buffer_decode (&index, &memlimit, NULL, indexdata, - &pos, options.backward_size) != LZMA_OK) - return 0; - - if (lzma_index_size (index) == options.backward_size) - { - ret = lzma_index_uncompressed_size (index); - } - - lzma_index_end (index, NULL); - return ret; -} - -static int -elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi) -{ - Elf_W (Shdr) *shdr; - uint8_t *compressed = NULL; - uint64_t memlimit = UINT64_MAX; /* no memory limit */ - size_t compressed_len, uncompressed_len; - - shdr = elf_w (find_section) (ei, ".gnu_debugdata"); - if (!shdr) - return 0; - - compressed = ((uint8_t *) ei->image) + shdr->sh_offset; - compressed_len = shdr->sh_size; - - uncompressed_len = xz_uncompressed_size (compressed, compressed_len); - if (uncompressed_len == 0) - { - Debug (1, "invalid .gnu_debugdata contents\n"); - return 0; - } - - mdi->size = uncompressed_len; - mdi->image = mmap (NULL, uncompressed_len, PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); - - if (mdi->image == MAP_FAILED) - return 0; - - size_t in_pos = 0, out_pos = 0; - lzma_ret lret; - lret = lzma_stream_buffer_decode (&memlimit, 0, NULL, - compressed, &in_pos, compressed_len, - mdi->image, &out_pos, mdi->size); - if (lret != LZMA_OK) - { - Debug (1, "LZMA decompression failed: %d\n", lret); - munmap (mdi->image, mdi->size); - return 0; - } - - return 1; -} -#else -static int -elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi) -{ - return 0; -} -#endif /* !HAVE_LZMA */ - -/* Find the ELF image that contains IP and return the "closest" - procedure name, if there is one. With some caching, this could be - sped up greatly, but until an application materializes that's - sensitive to the performance of this routine, why bother... */ - -HIDDEN int -elf_w (get_proc_name_in_image) (unw_addr_space_t as, struct elf_image *ei, - unsigned long segbase, - unsigned long mapoff, - unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp) -{ - Elf_W (Addr) load_offset; - Elf_W (Addr) min_dist = ~(Elf_W (Addr))0; - int ret; - - load_offset = elf_w (get_load_offset) (ei, segbase, mapoff); - ret = elf_w (lookup_symbol) (as, ip, ei, load_offset, buf, buf_len, &min_dist); - - /* If the ELF image has MiniDebugInfo embedded in it, look up the symbol in - there as well and replace the previously found if it is closer. */ - struct elf_image mdi; - if (elf_w (extract_minidebuginfo) (ei, &mdi)) - { - int ret_mdi = elf_w (lookup_symbol) (as, ip, &mdi, load_offset, buf, - buf_len, &min_dist); - - /* Closer symbol was found (possibly truncated). */ - if (ret_mdi == 0 || ret_mdi == -UNW_ENOMEM) - { - ret = ret_mdi; - } - - munmap (mdi.image, mdi.size); - } - - if (min_dist >= ei->size) - return -UNW_ENOINFO; /* not found */ - if (offp) - *offp = min_dist; - return ret; -} - -HIDDEN int -elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp) -{ - unsigned long segbase, mapoff; - struct elf_image ei; - int ret; - char file[PATH_MAX]; - - ret = tdep_get_elf_image (&ei, pid, ip, &segbase, &mapoff, file, PATH_MAX); - if (ret < 0) - return ret; - - ret = elf_w (load_debuglink) (file, &ei, 1); - if (ret < 0) - return ret; - - ret = elf_w (get_proc_name_in_image) (as, &ei, segbase, mapoff, ip, buf, buf_len, offp); - - munmap (ei.image, ei.size); - ei.image = NULL; - - return ret; -} - -HIDDEN Elf_W (Shdr)* -elf_w (find_section) (struct elf_image *ei, const char* secname) -{ - Elf_W (Ehdr) *ehdr = ei->image; - Elf_W (Shdr) *shdr; - char *strtab; - int i; - - if (!elf_w (valid_object) (ei)) - return 0; - - shdr = elf_w (section_table) (ei); - if (!shdr) - return 0; - - strtab = elf_w (string_table) (ei, ehdr->e_shstrndx); - if (!strtab) - return 0; - - for (i = 0; i < ehdr->e_shnum; ++i) - { - if (strcmp (strtab + shdr->sh_name, secname) == 0) - { - if (shdr->sh_offset + shdr->sh_size > ei->size) - { - Debug (1, "section \"%s\" outside image? (0x%lu > 0x%lu)\n", - secname, - (unsigned long) shdr->sh_offset + shdr->sh_size, - (unsigned long) ei->size); - return 0; - } - - Debug (16, "found section \"%s\" at 0x%lx\n", - secname, (unsigned long) shdr->sh_offset); - return shdr; - } - - shdr = (Elf_W (Shdr) *) (((char *) shdr) + ehdr->e_shentsize); - } - - /* section not found */ - return 0; -} - -/* Load a debug section, following .gnu_debuglink if appropriate - * Loads ei from file if not already mapped. - * If is_local, will also search sys directories /usr/local/dbg - * - * Returns 0 on success, failure otherwise. - * ei will be mapped to file or the located .gnu_debuglink from file - */ -HIDDEN int -elf_w (load_debuglink) (const char* file, struct elf_image *ei, int is_local) -{ - int ret; - Elf_W (Shdr) *shdr; - Elf_W (Ehdr) *prev_image = ei->image; - off_t prev_size = ei->size; - - if (!ei->image) - { - ret = elf_map_image(ei, file); - if (ret) - return ret; - } - - /* Ignore separate debug files which contain a .gnu_debuglink section. */ - if (is_local == -1) { - return 0; - } - - shdr = elf_w (find_section) (ei, ".gnu_debuglink"); - if (shdr) { - if (shdr->sh_size >= PATH_MAX || - (shdr->sh_offset + shdr->sh_size > ei->size)) - { - return 0; - } - - { - char linkbuf[shdr->sh_size]; - char *link = ((char *) ei->image) + shdr->sh_offset; - char *p; - static const char *debugdir = "/usr/lib/debug"; - char basedir[strlen(file) + 1]; - char newname[shdr->sh_size + strlen (debugdir) + strlen (file) + 9]; - - memcpy(linkbuf, link, shdr->sh_size); - - if (memchr (linkbuf, 0, shdr->sh_size) == NULL) - return 0; - - ei->image = NULL; - - Debug(1, "Found debuglink section, following %s\n", linkbuf); - - p = strrchr (file, '/'); - if (p != NULL) - { - memcpy (basedir, file, p - file); - basedir[p - file] = '\0'; - } - else - basedir[0] = 0; - - strcpy (newname, basedir); - strcat (newname, "/"); - strcat (newname, linkbuf); - ret = elf_w (load_debuglink) (newname, ei, -1); - - if (ret == -1) - { - strcpy (newname, basedir); - strcat (newname, "/.debug/"); - strcat (newname, linkbuf); - ret = elf_w (load_debuglink) (newname, ei, -1); - } - - if (ret == -1 && is_local == 1) - { - strcpy (newname, debugdir); - strcat (newname, basedir); - strcat (newname, "/"); - strcat (newname, linkbuf); - ret = elf_w (load_debuglink) (newname, ei, -1); - } - - if (ret == -1) - { - /* No debuglink file found even though .gnu_debuglink existed */ - ei->image = prev_image; - ei->size = prev_size; - - return 0; - } - else - { - munmap (prev_image, prev_size); - } - - return ret; - } - } - - return 0; -} diff --git a/contrib/libunwind/src/elfxx.h b/contrib/libunwind/src/elfxx.h deleted file mode 100644 index 830432c2ed1..00000000000 --- a/contrib/libunwind/src/elfxx.h +++ /dev/null @@ -1,101 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003, 2005 Hewlett-Packard Co - Copyright (C) 2007 David Mosberger-Tang - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include -#include - -#include "libunwind_i.h" - -#if ELF_CLASS == ELFCLASS32 -# define ELF_W(x) ELF32_##x -# define Elf_W(x) Elf32_##x -# define elf_w(x) _Uelf32_##x -#else -# define ELF_W(x) ELF64_##x -# define Elf_W(x) Elf64_##x -# define elf_w(x) _Uelf64_##x -#endif - -extern int elf_w (get_proc_name) (unw_addr_space_t as, - pid_t pid, unw_word_t ip, - char *buf, size_t len, - unw_word_t *offp); - -extern int elf_w (get_proc_name_in_image) (unw_addr_space_t as, - struct elf_image *ei, - unsigned long segbase, - unsigned long mapoff, - unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp); - -extern Elf_W (Shdr)* elf_w (find_section) (struct elf_image *ei, const char* secname); -extern int elf_w (load_debuglink) (const char* file, struct elf_image *ei, int is_local); - -static inline int -elf_w (valid_object) (struct elf_image *ei) -{ - if (ei->size <= EI_VERSION) - return 0; - - return (memcmp (ei->image, ELFMAG, SELFMAG) == 0 - && ((uint8_t *) ei->image)[EI_CLASS] == ELF_CLASS - && ((uint8_t *) ei->image)[EI_VERSION] != EV_NONE - && ((uint8_t *) ei->image)[EI_VERSION] <= EV_CURRENT); -} - -static inline int -elf_map_image (struct elf_image *ei, const char *path) -{ - struct stat stat; - int fd; - - fd = open (path, O_RDONLY); - if (fd < 0) - return -1; - - if (fstat (fd, &stat) < 0) - { - close (fd); - return -1; - } - - ei->size = stat.st_size; - ei->image = mmap (NULL, ei->size, PROT_READ, MAP_PRIVATE, fd, 0); - close (fd); - if (ei->image == MAP_FAILED) - return -1; - - if (!elf_w (valid_object) (ei)) - { - munmap(ei->image, ei->size); - return -1; - } - - return 0; -} diff --git a/contrib/libunwind/src/hppa/Gapply_reg_state.c b/contrib/libunwind/src/hppa/Gapply_reg_state.c deleted file mode 100644 index eec93046f56..00000000000 --- a/contrib/libunwind/src/hppa/Gapply_reg_state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); -} diff --git a/contrib/libunwind/src/hppa/Gcreate_addr_space.c b/contrib/libunwind/src/hppa/Gcreate_addr_space.c deleted file mode 100644 index 71186e0e7aa..00000000000 --- a/contrib/libunwind/src/hppa/Gcreate_addr_space.c +++ /dev/null @@ -1,54 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* - * hppa supports only big-endian. - */ - if (byte_order != 0 && byte_order != __BIG_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - return as; -#endif -} diff --git a/contrib/libunwind/src/hppa/Gget_proc_info.c b/contrib/libunwind/src/hppa/Gget_proc_info.c deleted file mode 100644 index ce7a950aabc..00000000000 --- a/contrib/libunwind/src/hppa/Gget_proc_info.c +++ /dev/null @@ -1,46 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) -{ - struct cursor *c = (struct cursor *) cursor; - - if (dwarf_make_proc_info (&c->dwarf) < 0) - { - /* On hppa, some key routines such as _start() and _dl_start() - are missing DWARF unwind info. We don't want to fail in that - case, because those frames are uninteresting and just mark - the end of the frame-chain anyhow. */ - memset (pi, 0, sizeof (*pi)); - pi->start_ip = c->dwarf.ip; - pi->end_ip = c->dwarf.ip + 4; - return 0; - } - *pi = c->dwarf.pi; - return 0; -} diff --git a/contrib/libunwind/src/hppa/Gget_save_loc.c b/contrib/libunwind/src/hppa/Gget_save_loc.c deleted file mode 100644 index 549366a833d..00000000000 --- a/contrib/libunwind/src/hppa/Gget_save_loc.c +++ /dev/null @@ -1,59 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) -{ - /* struct cursor *c = (struct cursor *) cursor; */ - dwarf_loc_t loc; - - loc = DWARF_NULL_LOC; /* default to "not saved" */ - -#warning FIX ME! - - memset (sloc, 0, sizeof (*sloc)); - - if (DWARF_IS_NULL_LOC (loc)) - { - sloc->type = UNW_SLT_NONE; - return 0; - } - -#if !defined(UNW_LOCAL_ONLY) - if (DWARF_IS_REG_LOC (loc)) - { - sloc->type = UNW_SLT_REG; - sloc->u.regnum = DWARF_GET_LOC (loc); - } - else -#endif - { - sloc->type = UNW_SLT_MEMORY; - sloc->u.addr = DWARF_GET_LOC (loc); - } - return 0; -} diff --git a/contrib/libunwind/src/hppa/Gglobal.c b/contrib/libunwind/src/hppa/Gglobal.c deleted file mode 100644 index 351a5015d68..00000000000 --- a/contrib/libunwind/src/hppa/Gglobal.c +++ /dev/null @@ -1,55 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2004-2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -HIDDEN define_lock (hppa_lock); -HIDDEN int tdep_init_done; - -HIDDEN void -tdep_init (void) -{ - intrmask_t saved_mask; - - sigfillset (&unwi_full_mask); - - lock_acquire (&hppa_lock, saved_mask); - { - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - mi_init (); - - dwarf_init (); - -#ifndef UNW_REMOTE_ONLY - hppa_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - } - out: - lock_release (&hppa_lock, saved_mask); -} diff --git a/contrib/libunwind/src/hppa/Ginit.c b/contrib/libunwind/src/hppa/Ginit.c deleted file mode 100644 index 28779c39ba5..00000000000 --- a/contrib/libunwind/src/hppa/Ginit.c +++ /dev/null @@ -1,194 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002, 2004 Hewlett-Packard Co - Copyright (C) 2007 David Mosberger-Tang - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -PROTECTED unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; - -static inline void * -uc_addr (ucontext_t *uc, int reg) -{ - void *addr; - - if ((unsigned) (reg - UNW_HPPA_GR) < 32) - addr = &uc->uc_mcontext.sc_gr[reg - UNW_HPPA_GR]; - else if ((unsigned) (reg - UNW_HPPA_FR) < 32) - addr = &uc->uc_mcontext.sc_fr[reg - UNW_HPPA_FR]; - else - addr = NULL; - return addr; -} - -# ifdef UNW_LOCAL_ONLY - -void * -_Uhppa_uc_addr (ucontext_t *uc, int reg) -{ - return uc_addr (uc, reg); -} - -# endif /* UNW_LOCAL_ONLY */ - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - -/* XXX fix me: there is currently no way to locate the dyn-info list - by a remote unwinder. On ia64, this is done via a special - unwind-table entry. Perhaps something similar can be done with - DWARF2 unwind info. */ - -static void -put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ - *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - if (write) - { - Debug (12, "mem[%x] <- %x\n", addr, *val); - *(unw_word_t *) addr = *val; - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "mem[%x] -> %x\n", addr, *val); - } - return 0; -} - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, - void *arg) -{ - unw_word_t *addr; - ucontext_t *uc = arg; - - if ((unsigned int) (reg - UNW_HPPA_FR) < 32) - goto badreg; - - addr = uc_addr (uc, reg); - if (!addr) - goto badreg; - - if (write) - { - *(unw_word_t *) addr = *val; - Debug (12, "%s <- %x\n", unw_regname (reg), *val); - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "%s -> %x\n", unw_regname (reg), *val); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - ucontext_t *uc = arg; - unw_fpreg_t *addr; - - if ((unsigned) (reg - UNW_HPPA_FR) > 32) - goto badreg; - - addr = uc_addr (uc, reg); - if (!addr) - goto badreg; - - if (write) - { - Debug (12, "%s <- %08x.%08x\n", - unw_regname (reg), val->raw.bits[1], val->raw.bits[0]); - *(unw_fpreg_t *) addr = *val; - } - else - { - *val = *(unw_fpreg_t *) addr; - Debug (12, "%s -> %08x.%08x\n", - unw_regname (reg), val->raw.bits[1], val->raw.bits[0]); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - /* attempt to access a non-preserved register */ - return -UNW_EBADREG; -} - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp); -} - -HIDDEN void -hppa_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; - local_addr_space.acc.find_proc_info = dwarf_find_proc_info; - local_addr_space.acc.put_unwind_info = put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = hppa_local_resume; - local_addr_space.acc.get_proc_name = get_static_proc_name; - unw_flush_cache (&local_addr_space, 0, 0); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/hppa/Ginit_local.c b/contrib/libunwind/src/hppa/Ginit_local.c deleted file mode 100644 index 5c59f48f880..00000000000 --- a/contrib/libunwind/src/hppa/Ginit_local.c +++ /dev/null @@ -1,77 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by ... - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "init.h" - -#ifdef UNW_REMOTE_ONLY - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - return -UNW_EINVAL; -} - -#else /* !UNW_REMOTE_ONLY */ - -static int -unw_init_local_common (unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) -{ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = unw_local_addr_space; - c->dwarf.as_arg = uc; - return common_init (c, use_prev_instr); -} - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - return unw_init_local_common(cursor, uc, 1); -} - -PROTECTED int -unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) -{ - if (!flag) - { - return unw_init_local_common(cursor, uc, 1); - } - else if (flag == UNW_INIT_SIGNAL_FRAME) - { - return unw_init_local_common(cursor, uc, 0); - } - else - { - return -UNW_EINVAL; - } -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/hppa/Ginit_remote.c b/contrib/libunwind/src/hppa/Ginit_remote.c deleted file mode 100644 index a4160fd191f..00000000000 --- a/contrib/libunwind/src/hppa/Ginit_remote.c +++ /dev/null @@ -1,46 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2004 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "init.h" -#include "unwind_i.h" - -PROTECTED int -unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) -{ -#ifdef UNW_LOCAL_ONLY - return -UNW_EINVAL; -#else /* !UNW_LOCAL_ONLY */ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = as; - c->dwarf.as_arg = as_arg; - return common_init (c, 0); -#endif /* !UNW_LOCAL_ONLY */ -} diff --git a/contrib/libunwind/src/hppa/Gis_signal_frame.c b/contrib/libunwind/src/hppa/Gis_signal_frame.c deleted file mode 100644 index 00e40c6ac15..00000000000 --- a/contrib/libunwind/src/hppa/Gis_signal_frame.c +++ /dev/null @@ -1,74 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ -#ifdef __linux__ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, w1, w2, w3, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - /* Check if IP points at sigreturn() sequence. On Linux, this normally is: - - rt_sigreturn: - 0x34190000 ldi 0, %r25 - 0x3414015a ldi __NR_rt_sigreturn,%r20 - 0xe4008200 be,l 0x100(%sr2,%r0),%sr0,%r31 - 0x08000240 nop - - When a signal interrupts a system call, the first word is instead: - - 0x34190002 ldi 1, %r25 - */ - ip = c->dwarf.ip; - if (!ip) - return 0; - if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 - || (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0 - || (ret = (*a->access_mem) (as, ip + 8, &w2, 0, arg)) < 0 - || (ret = (*a->access_mem) (as, ip + 12, &w3, 0, arg)) < 0) - { - Debug (1, "failed to read sigreturn code (ret=%d)\n", ret); - return ret; - } - ret = ((w0 == 0x34190000 || w0 == 0x34190002) - && w1 == 0x3414015a && w2 == 0xe4008200 && w3 == 0x08000240); - Debug (1, "(cursor=%p, ip=0x%08lx) -> %d\n", c, (unsigned) ip, ret); - return ret; -#else - printf ("%s: implement me\n", __FUNCTION__); -#endif - return -UNW_ENOINFO; -} diff --git a/contrib/libunwind/src/hppa/Greg_states_iterate.c b/contrib/libunwind/src/hppa/Greg_states_iterate.c deleted file mode 100644 index a39837a1781..00000000000 --- a/contrib/libunwind/src/hppa/Greg_states_iterate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_reg_states_iterate (&c->dwarf, cb, token); -} diff --git a/contrib/libunwind/src/hppa/Gregs.c b/contrib/libunwind/src/hppa/Gregs.c deleted file mode 100644 index da0542c81ff..00000000000 --- a/contrib/libunwind/src/hppa/Gregs.c +++ /dev/null @@ -1,87 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - struct dwarf_loc loc; - - switch (reg) - { - case UNW_HPPA_IP: - if (write) - c->dwarf.ip = *valp; /* update the IP cache */ - if (c->dwarf.pi_valid && (*valp < c->dwarf.pi.start_ip - || *valp >= c->dwarf.pi.end_ip)) - c->dwarf.pi_valid = 0; /* new IP outside of current proc */ - break; - - case UNW_HPPA_CFA: - case UNW_HPPA_SP: - if (write) - return -UNW_EREADONLYREG; - *valp = c->dwarf.cfa; - return 0; - - /* Do the exception-handling register remapping: */ - case UNW_HPPA_EH0: reg = UNW_HPPA_GR + 20; break; - case UNW_HPPA_EH1: reg = UNW_HPPA_GR + 21; break; - case UNW_HPPA_EH2: reg = UNW_HPPA_GR + 22; break; - case UNW_HPPA_EH3: reg = UNW_HPPA_GR + 31; break; - - default: - break; - } - - if ((unsigned) (reg - UNW_HPPA_GR) >= 32) - return -UNW_EBADREG; - - loc = c->dwarf.loc[reg]; - - if (write) - return dwarf_put (&c->dwarf, loc, *valp); - else - return dwarf_get (&c->dwarf, loc, valp); -} - -HIDDEN int -tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, - int write) -{ - struct dwarf_loc loc; - - if ((unsigned) (reg - UNW_HPPA_FR) >= 32) - return -UNW_EBADREG; - - loc = c->dwarf.loc[reg]; - - if (write) - return dwarf_putfp (&c->dwarf, loc, *valp); - else - return dwarf_getfp (&c->dwarf, loc, valp); -} diff --git a/contrib/libunwind/src/hppa/Gresume.c b/contrib/libunwind/src/hppa/Gresume.c deleted file mode 100644 index f6bc023f504..00000000000 --- a/contrib/libunwind/src/hppa/Gresume.c +++ /dev/null @@ -1,145 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2004 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -#ifndef UNW_REMOTE_ONLY - -#if defined(__linux) - -# include - -static NORETURN inline long -my_rt_sigreturn (void *new_sp, int in_syscall) -{ - register unsigned long r25 __asm__ ("r25") = (in_syscall != 0); - register unsigned long r20 __asm__ ("r20") = SYS_rt_sigreturn; - - __asm__ __volatile__ ("copy %0, %%sp\n" - "be,l 0x100(%%sr2,%%r0),%%sr0,%%r31\n" - "nop" - : - : "r"(new_sp), "r"(r20), "r"(r25) - : "memory"); - abort (); -} - -#endif /* __linux */ - -HIDDEN inline int -hppa_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ -#if defined(__linux) - struct cursor *c = (struct cursor *) cursor; - ucontext_t *uc = c->dwarf.as_arg; - - /* Ensure c->pi is up-to-date. On PA-RISC, it's relatively common to be - missing DWARF unwind info. We don't want to fail in that case, - because the frame-chain still would let us do a backtrace at - least. */ - dwarf_make_proc_info (&c->dwarf); - - if (unlikely (c->sigcontext_format != HPPA_SCF_NONE)) - { - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - - Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); - my_rt_sigreturn (sc, (sc->sc_flags & PARISC_SC_FLAG_IN_SYSCALL) != 0); - } - else - { - Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); - setcontext (uc); - } -#else -# warning Implement me! -#endif - return -UNW_EINVAL; -} - -#endif /* !UNW_REMOTE_ONLY */ - -/* This routine is responsible for copying the register values in - cursor C and establishing them as the current machine state. */ - -static inline int -establish_machine_state (struct cursor *c) -{ - int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, - int write, void *); - int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, - int write, void *); - unw_addr_space_t as = c->dwarf.as; - void *arg = c->dwarf.as_arg; - unw_fpreg_t fpval; - unw_word_t val; - int reg; - - access_reg = as->acc.access_reg; - access_fpreg = as->acc.access_fpreg; - - Debug (8, "copying out cursor state\n"); - - for (reg = 0; reg <= UNW_REG_LAST; ++reg) - { - Debug (16, "copying %s %d\n", unw_regname (reg), reg); - if (unw_is_fpreg (reg)) - { - if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) - (*access_fpreg) (as, reg, &fpval, 1, arg); - } - else - { - if (tdep_access_reg (c, reg, &val, 0) >= 0) - (*access_reg) (as, reg, &val, 1, arg); - } - } - return 0; -} - -PROTECTED int -unw_resume (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - Debug (1, "(cursor=%p)\n", c); - - if (!c->dwarf.ip) - { - /* This can happen easily when the frame-chain gets truncated - due to bad or missing unwind-info. */ - Debug (1, "refusing to resume execution at address 0\n"); - return -UNW_EINVAL; - } - - if ((ret = establish_machine_state (c)) < 0) - return ret; - - return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, - c->dwarf.as_arg); -} diff --git a/contrib/libunwind/src/hppa/Gstep.c b/contrib/libunwind/src/hppa/Gstep.c deleted file mode 100644 index b9e170a2d46..00000000000 --- a/contrib/libunwind/src/hppa/Gstep.c +++ /dev/null @@ -1,95 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" - -PROTECTED int -unw_step (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret, i; - - Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip); - - /* Try DWARF-based unwinding... */ - ret = dwarf_step (&c->dwarf); - - if (ret < 0 && ret != -UNW_ENOINFO) - { - Debug (2, "returning %d\n", ret); - return ret; - } - - if (unlikely (ret < 0)) - { - /* DWARF failed, let's see if we can follow the frame-chain - or skip over the signal trampoline. */ - - Debug (13, "dwarf_step() failed (ret=%d), trying fallback\n", ret); - - if (unw_is_signal_frame (cursor)) - { -#ifdef __linux__ - /* Assume that the trampoline is at the beginning of the - sigframe. */ - unw_word_t ip, sc_addr = c->dwarf.ip + LINUX_RT_SIGFRAME_UC_OFF; - dwarf_loc_t iaoq_loc = DWARF_LOC (sc_addr + LINUX_SC_IAOQ_OFF, 0); - - c->sigcontext_format = HPPA_SCF_LINUX_RT_SIGFRAME; - c->sigcontext_addr = sc_addr; - - if ((ret = dwarf_get (&c->dwarf, iaoq_loc, &ip)) < 0) - { - Debug (2, "failed to read IAOQ[1] (ret=%d)\n", ret); - return ret; - } - c->dwarf.ip = ip & ~0x3; /* mask out the privilege level */ - - for (i = 0; i < 32; ++i) - { - c->dwarf.loc[UNW_HPPA_GR + i] - = DWARF_LOC (sc_addr + LINUX_SC_GR_OFF + 4*i, 0); - c->dwarf.loc[UNW_HPPA_FR + i] - = DWARF_LOC (sc_addr + LINUX_SC_FR_OFF + 4*i, 0); - } - - if ((ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_HPPA_SP], - &c->dwarf.cfa)) < 0) - { - Debug (2, "failed to read SP (ret=%d)\n", ret); - return ret; - } -#else -# error Implement me! -#endif - } - else - c->dwarf.ip = 0; - } - ret = (c->dwarf.ip == 0) ? 0 : 1; - Debug (2, "returning %d\n", ret); - return ret; -} diff --git a/contrib/libunwind/src/hppa/Lapply_reg_state.c b/contrib/libunwind/src/hppa/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/hppa/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/hppa/Lcreate_addr_space.c b/contrib/libunwind/src/hppa/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901..00000000000 --- a/contrib/libunwind/src/hppa/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/contrib/libunwind/src/hppa/Lget_proc_info.c b/contrib/libunwind/src/hppa/Lget_proc_info.c deleted file mode 100644 index 69028b019fc..00000000000 --- a/contrib/libunwind/src/hppa/Lget_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info.c" -#endif diff --git a/contrib/libunwind/src/hppa/Lget_save_loc.c b/contrib/libunwind/src/hppa/Lget_save_loc.c deleted file mode 100644 index 9ea048a9076..00000000000 --- a/contrib/libunwind/src/hppa/Lget_save_loc.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_save_loc.c" -#endif diff --git a/contrib/libunwind/src/hppa/Lglobal.c b/contrib/libunwind/src/hppa/Lglobal.c deleted file mode 100644 index 6d7b489e14b..00000000000 --- a/contrib/libunwind/src/hppa/Lglobal.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/contrib/libunwind/src/hppa/Linit.c b/contrib/libunwind/src/hppa/Linit.c deleted file mode 100644 index e9abfdd46a3..00000000000 --- a/contrib/libunwind/src/hppa/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/contrib/libunwind/src/hppa/Linit_local.c b/contrib/libunwind/src/hppa/Linit_local.c deleted file mode 100644 index 68a1687e854..00000000000 --- a/contrib/libunwind/src/hppa/Linit_local.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_local.c" -#endif diff --git a/contrib/libunwind/src/hppa/Linit_remote.c b/contrib/libunwind/src/hppa/Linit_remote.c deleted file mode 100644 index 58cb04ab7cd..00000000000 --- a/contrib/libunwind/src/hppa/Linit_remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_remote.c" -#endif diff --git a/contrib/libunwind/src/hppa/Lis_signal_frame.c b/contrib/libunwind/src/hppa/Lis_signal_frame.c deleted file mode 100644 index b9a7c4f51ad..00000000000 --- a/contrib/libunwind/src/hppa/Lis_signal_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gis_signal_frame.c" -#endif diff --git a/contrib/libunwind/src/hppa/Lreg_states_iterate.c b/contrib/libunwind/src/hppa/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/hppa/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/hppa/Lregs.c b/contrib/libunwind/src/hppa/Lregs.c deleted file mode 100644 index 2c9c75cd7d9..00000000000 --- a/contrib/libunwind/src/hppa/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/contrib/libunwind/src/hppa/Lresume.c b/contrib/libunwind/src/hppa/Lresume.c deleted file mode 100644 index 41a8cf003de..00000000000 --- a/contrib/libunwind/src/hppa/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/contrib/libunwind/src/hppa/Lstep.c b/contrib/libunwind/src/hppa/Lstep.c deleted file mode 100644 index c1ac3c7547f..00000000000 --- a/contrib/libunwind/src/hppa/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/contrib/libunwind/src/hppa/get_accessors.c b/contrib/libunwind/src/hppa/get_accessors.c deleted file mode 100644 index 873a38c8760..00000000000 --- a/contrib/libunwind/src/hppa/get_accessors.c +++ /dev/null @@ -1,35 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by ... - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED unw_accessors_t * -unw_get_accessors (unw_addr_space_t as) -{ - if (!tdep_init_done) - tdep_init (); - - return &as->acc; -} diff --git a/contrib/libunwind/src/hppa/getcontext.S b/contrib/libunwind/src/hppa/getcontext.S deleted file mode 100644 index ec7554a0259..00000000000 --- a/contrib/libunwind/src/hppa/getcontext.S +++ /dev/null @@ -1,74 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#define SPILL(n) stw %r##n, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_GR_OFF+4*(n))(%r26) - -#include "offsets.h" - - .align 4 - .protected _Uhppa_getcontext - .global _Uhppa_getcontext - .proc - .callinfo -_Uhppa_getcontext: - SPILL (2) /* return-pointer */ - SPILL (3) /* frame pointer */ - SPILL (4) /* 2nd-ary frame pointer */ - SPILL (5) /* preserved register */ - SPILL (6) /* preserved register */ - SPILL (7) /* preserved register */ - SPILL (8) /* preserved register */ - SPILL (9) /* preserved register */ - SPILL (10) /* preserved register */ - SPILL (11) /* preserved register */ - SPILL (12) /* preserved register */ - SPILL (13) /* preserved register */ - SPILL (14) /* preserved register */ - SPILL (15) /* preserved register */ - SPILL (16) /* preserved register */ - SPILL (17) /* preserved register */ - SPILL (18) /* preserved register */ - SPILL (19) /* linkage-table register */ - SPILL (27) /* global-data pointer */ - SPILL (30) /* stack pointer */ - - ldo (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FR_OFF)(%r26), %r29 - fstds,ma %fr12, 8(%r29) - fstds,ma %fr13, 8(%r29) - fstds,ma %fr14, 8(%r29) - fstds,ma %fr15, 8(%r29) - fstds,ma %fr16, 8(%r29) - fstds,ma %fr17, 8(%r29) - fstds,ma %fr18, 8(%r29) - fstds,ma %fr19, 8(%r29) - fstds,ma %fr20, 8(%r29) - fstds %fr21, 8(%r29) - - bv,n %r0(%rp) - .procend -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/hppa/init.h b/contrib/libunwind/src/hppa/init.h deleted file mode 100644 index 4e23b861327..00000000000 --- a/contrib/libunwind/src/hppa/init.h +++ /dev/null @@ -1,47 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by ... - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static inline int -common_init (struct cursor *c, unsigned use_prev_instr) -{ - int ret; - - c->dwarf.loc[UNW_HPPA_IP] = DWARF_REG_LOC (&c->dwarf, UNW_HPPA_IP); - c->dwarf.loc[UNW_HPPA_SP] = DWARF_REG_LOC (&c->dwarf, UNW_HPPA_SP); - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_HPPA_IP], &c->dwarf.ip); - if (ret < 0) - return ret; - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_HPPA_SP], &c->dwarf.cfa); - if (ret < 0) - return ret; - - c->dwarf.stash_frames = 0; - c->dwarf.use_prev_instr = use_prev_instr; - return 0; -} diff --git a/contrib/libunwind/src/hppa/offsets.h b/contrib/libunwind/src/hppa/offsets.h deleted file mode 100644 index 24e6453ac4f..00000000000 --- a/contrib/libunwind/src/hppa/offsets.h +++ /dev/null @@ -1,17 +0,0 @@ -#define LINUX_UC_FLAGS_OFF 0x000 -#define LINUX_UC_LINK_OFF 0x004 -#define LINUX_UC_STACK_OFF 0x008 -#define LINUX_UC_MCONTEXT_OFF 0x018 -#define LINUX_UC_SIGMASK_OFF 0x1b8 - -#define LINUX_SC_FLAGS_OFF 0x000 -#define LINUX_SC_GR_OFF 0x004 -#define LINUX_SC_FR_OFF 0x088 -#define LINUX_SC_IASQ_OFF 0x188 -#define LINUX_SC_IAOQ_OFF 0x190 -#define LINUX_SC_SAR_OFF 0x198 - -/* The signal frame contains 4 words of space for the sigreturn - trampoline, the siginfo structure, and then the sigcontext - structure. See include/asm-parisc/compat_rt_sigframe.h. */ -#define LINUX_RT_SIGFRAME_UC_OFF 0xac diff --git a/contrib/libunwind/src/hppa/regname.c b/contrib/libunwind/src/hppa/regname.c deleted file mode 100644 index 06dfae75015..00000000000 --- a/contrib/libunwind/src/hppa/regname.c +++ /dev/null @@ -1,50 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2004-2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static const char *regname[] = - { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", - "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7", - "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15", - "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23", - "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31", - "ip", - "eh0", "eh1", "eh2", "eh3", - "cfa" - }; - -PROTECTED const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) - return regname[reg]; - else - return "???"; -} diff --git a/contrib/libunwind/src/hppa/setcontext.S b/contrib/libunwind/src/hppa/setcontext.S deleted file mode 100644 index a36ea35cc61..00000000000 --- a/contrib/libunwind/src/hppa/setcontext.S +++ /dev/null @@ -1,77 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* The setcontext() in glibc is a no-op (as of 4 Dec 2004), so we have - to implement something useful on our own here. */ - -#define FILL(n) ldw (LINUX_UC_MCONTEXT_OFF+LINUX_SC_GR_OFF+4*(n))(%r26),%r##n - -#include "offsets.h" - - .align 4 - .global _Uhppa_setcontext - .protected _Uhppa_setcontext - .proc - .callinfo -_Uhppa_setcontext: - FILL (2) /* return-pointer */ - FILL (3) /* frame pointer */ - FILL (4) /* 2nd-ary frame pointer */ - FILL (5) /* preserved register */ - FILL (6) /* preserved register */ - FILL (7) /* preserved register */ - FILL (8) /* preserved register */ - FILL (9) /* preserved register */ - FILL (10) /* preserved register */ - FILL (11) /* preserved register */ - FILL (12) /* preserved register */ - FILL (13) /* preserved register */ - FILL (14) /* preserved register */ - FILL (15) /* preserved register */ - FILL (16) /* preserved register */ - FILL (17) /* preserved register */ - FILL (18) /* preserved register */ - FILL (19) /* linkage-table register */ - FILL (27) /* global-data pointer */ - FILL (30) /* stack pointer */ - - ldo (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FR_OFF)(%r26), %r29 - fldds,ma 8(%r29), %fr12 - fldds,ma 8(%r29), %fr13 - fldds,ma 8(%r29), %fr14 - fldds,ma 8(%r29), %fr15 - fldds,ma 8(%r29), %fr16 - fldds,ma 8(%r29), %fr17 - fldds,ma 8(%r29), %fr18 - fldds,ma 8(%r29), %fr19 - fldds,ma 8(%r29), %fr20 - fldds 8(%r29), %fr21 - - bv,n %r0(%rp) - .procend -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/hppa/siglongjmp.S b/contrib/libunwind/src/hppa/siglongjmp.S deleted file mode 100644 index 34878dbe8f3..00000000000 --- a/contrib/libunwind/src/hppa/siglongjmp.S +++ /dev/null @@ -1,16 +0,0 @@ - /* Dummy implementation for now. */ - - .globl _UI_siglongjmp_cont - .globl _UI_longjmp_cont - -_UI_siglongjmp_cont: -_UI_longjmp_cont: - .proc - .callinfo -#warning fix me - bv %r0(%rp) - .procend -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/hppa/tables.c b/contrib/libunwind/src/hppa/tables.c deleted file mode 100644 index 5104d4d3429..00000000000 --- a/contrib/libunwind/src/hppa/tables.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "unwind_i.h" - -static inline int -is_local_addr_space (unw_addr_space_t as) -{ - extern unw_addr_space_t _ULhppa_local_addr_space; - - return (as == _Uhppa_local_addr_space -#ifndef UNW_REMOTE_ONLY - || as == _ULhppa_local_addr_space -#endif - ); -} - -HIDDEN int -tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, int need_unwind_info, void *arg) -{ - printf ("%s: begging to get implemented...\n", __FUNCTION__); - return 0; -} - -HIDDEN int -tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, - unw_proc_info_t *pi, int need_unwind_info, void *arg) -{ - printf ("%s: the biggest beggar of them all...\n", __FUNCTION__); - return 0; -} - -HIDDEN void -tdep_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg) -{ - if (!pi->unwind_info) - return; - - if (!is_local_addr_space (as)) - { - free (pi->unwind_info); - pi->unwind_info = NULL; - } -} diff --git a/contrib/libunwind/src/hppa/unwind_i.h b/contrib/libunwind/src/hppa/unwind_i.h deleted file mode 100644 index cafeab57b88..00000000000 --- a/contrib/libunwind/src/hppa/unwind_i.h +++ /dev/null @@ -1,47 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include - -#include - -#include "libunwind_i.h" - -#define hppa_lock UNW_OBJ(lock) -#define hppa_local_resume UNW_OBJ(local_resume) -#define hppa_local_addr_space_init UNW_OBJ(local_addr_space_init) -#define hppa_scratch_loc UNW_OBJ(scratch_loc) -#define setcontext UNW_ARCH_OBJ (setcontext) - -extern void hppa_local_addr_space_init (void); -extern int hppa_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, - void *arg); -extern dwarf_loc_t hppa_scratch_loc (struct cursor *c, unw_regnum_t reg); -extern int setcontext (const ucontext_t *ucp); - -#endif /* unwind_i_h */ diff --git a/contrib/libunwind/src/ia64/Gapply_reg_state.c b/contrib/libunwind/src/ia64/Gapply_reg_state.c deleted file mode 100644 index a049b57ecae..00000000000 --- a/contrib/libunwind/src/ia64/Gapply_reg_state.c +++ /dev/null @@ -1,39 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - // Needs dwarf support on ia64 - // return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); - return -UNW_EINVAL; -} diff --git a/contrib/libunwind/src/ia64/Gcreate_addr_space.c b/contrib/libunwind/src/ia64/Gcreate_addr_space.c deleted file mode 100644 index 20cf5d8bf12..00000000000 --- a/contrib/libunwind/src/ia64/Gcreate_addr_space.c +++ /dev/null @@ -1,63 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* - * IA-64 supports only big or little-endian, not weird stuff like - * PDP_ENDIAN. - */ - if (byte_order != 0 - && byte_order != __LITTLE_ENDIAN - && byte_order != __BIG_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - if (byte_order == 0) - /* use host default: */ - as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); - else - as->big_endian = (byte_order == __BIG_ENDIAN); - return as; -#endif -} diff --git a/contrib/libunwind/src/ia64/Gfind_unwind_table.c b/contrib/libunwind/src/ia64/Gfind_unwind_table.c deleted file mode 100644 index 9fd2707ace4..00000000000 --- a/contrib/libunwind/src/ia64/Gfind_unwind_table.c +++ /dev/null @@ -1,143 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include -#include -#include -#include - -#include - -#include "libunwind_i.h" -#include "elf64.h" - -static unw_word_t -find_gp (struct elf_dyn_info *edi, Elf64_Phdr *pdyn, Elf64_Addr load_base) -{ - Elf64_Off soff, str_soff; - Elf64_Ehdr *ehdr = edi->ei.image; - Elf64_Shdr *shdr; - Elf64_Shdr *str_shdr; - Elf64_Addr gp = 0; - char *strtab; - int i; - - if (pdyn) - { - /* If we have a PT_DYNAMIC program header, fetch the gp-value - from the DT_PLTGOT entry. */ - Elf64_Dyn *dyn = (Elf64_Dyn *) (pdyn->p_offset + (char *) edi->ei.image); - for (; dyn->d_tag != DT_NULL; ++dyn) - if (dyn->d_tag == DT_PLTGOT) - { - gp = (Elf64_Addr) dyn->d_un.d_ptr + load_base; - goto done; - } - } - - /* Without a PT_DYAMIC header, lets try to look for a non-empty .opd - section. If there is such a section, we know it's full of - function descriptors, and we can simply pick up the gp from the - second word of the first entry in this table. */ - - soff = ehdr->e_shoff; - str_soff = soff + (ehdr->e_shstrndx * ehdr->e_shentsize); - - if (soff + ehdr->e_shnum * ehdr->e_shentsize > edi->ei.size) - { - Debug (1, "section table outside of image? (%lu > %lu)", - soff + ehdr->e_shnum * ehdr->e_shentsize, - edi->ei.size); - goto done; - } - - shdr = (Elf64_Shdr *) ((char *) edi->ei.image + soff); - str_shdr = (Elf64_Shdr *) ((char *) edi->ei.image + str_soff); - strtab = (char *) edi->ei.image + str_shdr->sh_offset; - for (i = 0; i < ehdr->e_shnum; ++i) - { - if (strcmp (strtab + shdr->sh_name, ".opd") == 0 - && shdr->sh_size >= 16) - { - gp = ((Elf64_Addr *) ((char *) edi->ei.image + shdr->sh_offset))[1]; - goto done; - } - shdr = (Elf64_Shdr *) (((char *) shdr) + ehdr->e_shentsize); - } - - done: - Debug (16, "image at %p, gp = %lx\n", edi->ei.image, gp); - return gp; -} - -int -ia64_find_unwind_table (struct elf_dyn_info *edi, unw_addr_space_t as, - char *path, unw_word_t segbase, unw_word_t mapoff, - unw_word_t ip) -{ - Elf64_Phdr *phdr, *ptxt = NULL, *punw = NULL, *pdyn = NULL; - Elf64_Ehdr *ehdr; - int i; - - if (!_Uelf64_valid_object (&edi->ei)) - return -UNW_ENOINFO; - - ehdr = edi->ei.image; - phdr = (Elf64_Phdr *) ((char *) edi->ei.image + ehdr->e_phoff); - - for (i = 0; i < ehdr->e_phnum; ++i) - { - switch (phdr[i].p_type) - { - case PT_LOAD: - if (phdr[i].p_offset == mapoff) - ptxt = phdr + i; - break; - - case PT_IA_64_UNWIND: - punw = phdr + i; - break; - - case PT_DYNAMIC: - pdyn = phdr + i; - break; - - default: - break; - } - } - if (!ptxt || !punw) - return 0; - - edi->di_cache.start_ip = segbase; - edi->di_cache.end_ip = edi->di_cache.start_ip + ptxt->p_memsz; - edi->di_cache.gp = find_gp (edi, pdyn, segbase - ptxt->p_vaddr); - edi->di_cache.format = UNW_INFO_FORMAT_TABLE; - edi->di_cache.u.ti.name_ptr = 0; - edi->di_cache.u.ti.segbase = segbase; - edi->di_cache.u.ti.table_len = punw->p_memsz / sizeof (unw_word_t); - edi->di_cache.u.ti.table_data = (unw_word_t *) - ((char *) edi->ei.image + (punw->p_vaddr - ptxt->p_vaddr)); - return 1; -} diff --git a/contrib/libunwind/src/ia64/Gget_proc_info.c b/contrib/libunwind/src/ia64/Gget_proc_info.c deleted file mode 100644 index 6b4722d5d66..00000000000 --- a/contrib/libunwind/src/ia64/Gget_proc_info.c +++ /dev/null @@ -1,38 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - if ((ret = ia64_make_proc_info (c)) < 0) - return ret; - *pi = c->pi; - return 0; -} diff --git a/contrib/libunwind/src/ia64/Gget_save_loc.c b/contrib/libunwind/src/ia64/Gget_save_loc.c deleted file mode 100644 index fc37ad9dc94..00000000000 --- a/contrib/libunwind/src/ia64/Gget_save_loc.c +++ /dev/null @@ -1,168 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2003, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "rse.h" - -#include "offsets.h" -#include "regs.h" - -PROTECTED int -unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) -{ - struct cursor *c = (struct cursor *) cursor; - ia64_loc_t loc, reg_loc; - uint8_t nat_bitnr; - int ret; - - loc = IA64_NULL_LOC; /* default to "not saved" */ - - switch (reg) - { - /* frame registers */ - case UNW_IA64_BSP: - case UNW_REG_SP: - default: - break; - - case UNW_REG_IP: - loc = c->loc[IA64_REG_IP]; - break; - - /* preserved registers: */ - case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7: - loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_GR + 4))]; - break; - - case UNW_IA64_NAT + 4 ... UNW_IA64_NAT + 7: - loc = c->loc[IA64_REG_NAT4 + (reg - (UNW_IA64_NAT + 4))]; - reg_loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_NAT + 4))]; - nat_bitnr = c->nat_bitnr[reg - (UNW_IA64_NAT + 4)]; - if (IA64_IS_FP_LOC (reg_loc)) - /* NaT bit saved as a NaTVal. */ - loc = reg_loc; - break; - - case UNW_IA64_FR + 2: loc = c->loc[IA64_REG_F2]; break; - case UNW_IA64_FR + 3: loc = c->loc[IA64_REG_F3]; break; - case UNW_IA64_FR + 4: loc = c->loc[IA64_REG_F4]; break; - case UNW_IA64_FR + 5: loc = c->loc[IA64_REG_F5]; break; - case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31: - loc = c->loc[IA64_REG_F16 + (reg - (UNW_IA64_FR + 16))]; - break; - - case UNW_IA64_AR_BSP: loc = c->loc[IA64_REG_BSP]; break; - case UNW_IA64_AR_BSPSTORE: loc = c->loc[IA64_REG_BSPSTORE]; break; - case UNW_IA64_AR_PFS: loc = c->loc[IA64_REG_PFS]; break; - case UNW_IA64_AR_RNAT: loc = c->loc[IA64_REG_RNAT]; break; - case UNW_IA64_AR_UNAT: loc = c->loc[IA64_REG_UNAT]; break; - case UNW_IA64_AR_LC: loc = c->loc[IA64_REG_LC]; break; - case UNW_IA64_AR_FPSR: loc = c->loc[IA64_REG_FPSR]; break; - case UNW_IA64_BR + 1: loc = c->loc[IA64_REG_B1]; break; - case UNW_IA64_BR + 2: loc = c->loc[IA64_REG_B2]; break; - case UNW_IA64_BR + 3: loc = c->loc[IA64_REG_B3]; break; - case UNW_IA64_BR + 4: loc = c->loc[IA64_REG_B4]; break; - case UNW_IA64_BR + 5: loc = c->loc[IA64_REG_B5]; break; - case UNW_IA64_CFM: loc = c->cfm_loc; break; - case UNW_IA64_PR: loc = c->loc[IA64_REG_PR]; break; - - case UNW_IA64_GR + 32 ... UNW_IA64_GR + 127: /* stacked reg */ - reg = rotate_gr (c, reg - UNW_IA64_GR); - ret = ia64_get_stacked (c, reg, &loc, NULL); - if (ret < 0) - return ret; - break; - - case UNW_IA64_NAT + 32 ... UNW_IA64_NAT + 127: /* stacked reg */ - reg = rotate_gr (c, reg - UNW_IA64_NAT); - ret = ia64_get_stacked (c, reg, NULL, &loc); - break; - - case UNW_IA64_AR_EC: - loc = c->cfm_loc; - break; - - /* scratch & special registers: */ - - case UNW_IA64_GR + 0: - case UNW_IA64_GR + 1: /* global pointer */ - case UNW_IA64_NAT + 0: - case UNW_IA64_NAT + 1: /* global pointer */ - case UNW_IA64_FR + 0: - case UNW_IA64_FR + 1: - break; - - case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3: - case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31: - loc = ia64_scratch_loc (c, reg, &nat_bitnr); - break; - - case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3: - case UNW_IA64_GR + 8 ... UNW_IA64_GR + 31: - case UNW_IA64_BR + 0: - case UNW_IA64_BR + 6: - case UNW_IA64_BR + 7: - case UNW_IA64_AR_RSC: - case UNW_IA64_AR_CSD: - case UNW_IA64_AR_SSD: - case UNW_IA64_AR_CCV: - loc = ia64_scratch_loc (c, reg, NULL); - break; - - case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15: - loc = ia64_scratch_loc (c, reg, NULL); - break; - - case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127: - reg = rotate_fr (c, reg - UNW_IA64_FR) + UNW_IA64_FR; - loc = ia64_scratch_loc (c, reg, NULL); - break; - } - - memset (sloc, 0, sizeof (*sloc)); - - if (IA64_IS_NULL_LOC (loc)) - { - sloc->type = UNW_SLT_NONE; - return 0; - } - -#if !defined(UNW_LOCAL_ONLY) - if (IA64_IS_REG_LOC (loc)) - { - sloc->type = UNW_SLT_REG; - sloc->u.regnum = IA64_GET_REG (loc); - sloc->extra.nat_bitnr = nat_bitnr; - } - else -#endif - { - sloc->type = UNW_SLT_MEMORY; - sloc->u.addr = IA64_GET_ADDR (loc); - sloc->extra.nat_bitnr = nat_bitnr; - } - return 0; -} diff --git a/contrib/libunwind/src/ia64/Gglobal.c b/contrib/libunwind/src/ia64/Gglobal.c deleted file mode 100644 index 5c6156f0e22..00000000000 --- a/contrib/libunwind/src/ia64/Gglobal.c +++ /dev/null @@ -1,122 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -HIDDEN struct ia64_global_unwind_state unw = - { - .lock = PTHREAD_MUTEX_INITIALIZER, - .save_order = { - IA64_REG_IP, IA64_REG_PFS, IA64_REG_PSP, IA64_REG_PR, - IA64_REG_UNAT, IA64_REG_LC, IA64_REG_FPSR, IA64_REG_PRI_UNAT_GR - }, -#if UNW_DEBUG - .preg_name = { - "pri_unat_gr", "pri_unat_mem", "psp", "bsp", "bspstore", - "ar.pfs", "ar.rnat", "rp", - "r4", "r5", "r6", "r7", - "nat4", "nat5", "nat6", "nat7", - "ar.unat", "pr", "ar.lc", "ar.fpsr", - "b1", "b2", "b3", "b4", "b5", - "f2", "f3", "f4", "f5", - "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", - "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31" - } -#endif -}; - -HIDDEN void -tdep_init (void) -{ - const uint8_t f1_bytes[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - const uint8_t nat_val_bytes[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - const uint8_t int_val_bytes[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x3e, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - intrmask_t saved_mask; - uint8_t *lep, *bep; - long i; - - sigfillset (&unwi_full_mask); - - lock_acquire (&unw.lock, saved_mask); - { - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - mi_init (); - - mempool_init (&unw.reg_state_pool, sizeof (struct ia64_reg_state), 0); - mempool_init (&unw.labeled_state_pool, - sizeof (struct ia64_labeled_state), 0); - - unw.read_only.r0 = 0; - unw.read_only.f0.raw.bits[0] = 0; - unw.read_only.f0.raw.bits[1] = 0; - - lep = (uint8_t *) &unw.read_only.f1_le + 16; - bep = (uint8_t *) &unw.read_only.f1_be; - for (i = 0; i < 16; ++i) - { - *--lep = f1_bytes[i]; - *bep++ = f1_bytes[i]; - } - - lep = (uint8_t *) &unw.nat_val_le + 16; - bep = (uint8_t *) &unw.nat_val_be; - for (i = 0; i < 16; ++i) - { - *--lep = nat_val_bytes[i]; - *bep++ = nat_val_bytes[i]; - } - - lep = (uint8_t *) &unw.int_val_le + 16; - bep = (uint8_t *) &unw.int_val_be; - for (i = 0; i < 16; ++i) - { - *--lep = int_val_bytes[i]; - *bep++ = int_val_bytes[i]; - } - - assert (8*sizeof(unw_hash_index_t) >= IA64_LOG_UNW_HASH_SIZE); - -#ifndef UNW_REMOTE_ONLY - ia64_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - } - out: - lock_release (&unw.lock, saved_mask); -} diff --git a/contrib/libunwind/src/ia64/Ginit.c b/contrib/libunwind/src/ia64/Ginit.c deleted file mode 100644 index 395450ec9ab..00000000000 --- a/contrib/libunwind/src/ia64/Ginit.c +++ /dev/null @@ -1,505 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2005 Hewlett-Packard Co - Copyright (C) 2007 David Mosberger-Tang - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -#ifdef HAVE_SYS_UC_ACCESS_H -# include -#endif - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -PROTECTED unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; - -#ifdef HAVE_SYS_UC_ACCESS_H - -#else /* !HAVE_SYS_UC_ACCESS_H */ - -HIDDEN void * -tdep_uc_addr (ucontext_t *uc, int reg, uint8_t *nat_bitnr) -{ - return inlined_uc_addr (uc, reg, nat_bitnr); -} - -#endif /* !HAVE_SYS_UC_ACCESS_H */ - -static void -put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ -#ifndef UNW_LOCAL_ONLY -# pragma weak _U_dyn_info_list_addr - if (!_U_dyn_info_list_addr) - return -UNW_ENOINFO; -#endif - *dyn_info_list_addr = _U_dyn_info_list_addr (); - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - if (write) - { - Debug (12, "mem[%lx] <- %lx\n", addr, *val); - *(unw_word_t *) addr = *val; - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "mem[%lx] -> %lx\n", addr, *val); - } - return 0; -} - -#ifdef HAVE_SYS_UC_ACCESS_H - -#define SYSCALL_CFM_SAVE_REG 11 /* on a syscall, ar.pfs is saved in r11 */ -#define REASON_SYSCALL 0 - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, - void *arg) -{ - ucontext_t *uc = arg; - unsigned int nat, mask; - uint64_t value; - uint16_t reason; - int ret; - - __uc_get_reason (uc, &reason); - - switch (reg) - { - case UNW_IA64_GR ... UNW_IA64_GR + 31: - if ((ret = __uc_get_grs (uc, (reg - UNW_IA64_GR), 1, &value, &nat))) - break; - - if (write) - ret = __uc_set_grs (uc, (reg - UNW_IA64_GR), 1, val, nat); - else - *val = value; - break; - - case UNW_IA64_NAT ... UNW_IA64_NAT + 31: - if ((ret = __uc_get_grs (uc, (reg - UNW_IA64_GR), 1, &value, &nat))) - break; - - mask = 1 << (reg - UNW_IA64_GR); - - if (write) - { - if (*val) - nat |= mask; - else - nat &= ~mask; - ret = __uc_set_grs (uc, (reg - UNW_IA64_GR), 1, &value, nat); - } - else - *val = (nat & mask) != 0; - break; - - case UNW_IA64_AR ... UNW_IA64_AR + 127: - if (reg == UNW_IA64_AR_BSP) - { - if (write) - ret = __uc_set_ar (uc, (reg - UNW_IA64_AR), *val); - else - ret = __uc_get_ar (uc, (reg - UNW_IA64_AR), val); - } - else if (reg == UNW_IA64_AR_PFS && reason == REASON_SYSCALL) - { - /* As of HP-UX 11.22, getcontext() does not have unwind info - and because of that, we need to hack thins manually here. - Hopefully, this is OK because the HP-UX kernel also needs - to know where AR.PFS has been saved, so the use of - register r11 for this purpose is pretty much nailed - down. */ - if (write) - ret = __uc_set_grs (uc, SYSCALL_CFM_SAVE_REG, 1, val, 0); - else - ret = __uc_get_grs (uc, SYSCALL_CFM_SAVE_REG, 1, val, &nat); - } - else - { - if (write) - ret = __uc_set_ar (uc, (reg - UNW_IA64_AR), *val); - else - ret = __uc_get_ar (uc, (reg - UNW_IA64_AR), val); - } - break; - - case UNW_IA64_BR ... UNW_IA64_BR + 7: - if (write) - ret = __uc_set_brs (uc, (reg - UNW_IA64_BR), 1, val); - else - ret = __uc_get_brs (uc, (reg - UNW_IA64_BR), 1, val); - break; - - case UNW_IA64_PR: - if (write) - ret = __uc_set_prs (uc, *val); - else - ret = __uc_get_prs (uc, val); - break; - - case UNW_IA64_IP: - if (write) - ret = __uc_set_ip (uc, *val); - else - ret = __uc_get_ip (uc, val); - break; - - case UNW_IA64_CFM: - if (write) - ret = __uc_set_cfm (uc, *val); - else - ret = __uc_get_cfm (uc, val); - break; - - case UNW_IA64_FR ... UNW_IA64_FR + 127: - default: - ret = EINVAL; - break; - } - - if (ret != 0) - { - Debug (1, "failed to %s %s (ret = %d)\n", - write ? "write" : "read", unw_regname (reg), ret); - return -UNW_EBADREG; - } - - if (write) - Debug (12, "%s <- %lx\n", unw_regname (reg), *val); - else - Debug (12, "%s -> %lx\n", unw_regname (reg), *val); - return 0; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - ucontext_t *uc = arg; - fp_regval_t fp_regval; - int ret; - - switch (reg) - { - case UNW_IA64_FR ... UNW_IA64_FR + 127: - if (write) - { - memcpy (&fp_regval, val, sizeof (fp_regval)); - ret = __uc_set_frs (uc, (reg - UNW_IA64_FR), 1, &fp_regval); - } - else - { - ret = __uc_get_frs (uc, (reg - UNW_IA64_FR), 1, &fp_regval); - memcpy (val, &fp_regval, sizeof (*val)); - } - break; - - default: - ret = EINVAL; - break; - } - if (ret != 0) - return -UNW_EBADREG; - - return 0; -} - -#else /* !HAVE_SYS_UC_ACCESS_H */ - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, - void *arg) -{ - unw_word_t *addr, mask; - ucontext_t *uc = arg; - - if (reg >= UNW_IA64_NAT + 4 && reg <= UNW_IA64_NAT + 7) - { - mask = ((unw_word_t) 1) << (reg - UNW_IA64_NAT); - if (write) - { - if (*val) - uc->uc_mcontext.sc_nat |= mask; - else - uc->uc_mcontext.sc_nat &= ~mask; - } - else - *val = (uc->uc_mcontext.sc_nat & mask) != 0; - - if (write) - Debug (12, "%s <- %lx\n", unw_regname (reg), *val); - else - Debug (12, "%s -> %lx\n", unw_regname (reg), *val); - return 0; - } - - addr = tdep_uc_addr (uc, reg, NULL); - if (!addr) - goto badreg; - - if (write) - { - if (ia64_read_only_reg (addr)) - { - Debug (16, "attempt to write read-only register\n"); - return -UNW_EREADONLYREG; - } - *addr = *val; - Debug (12, "%s <- %lx\n", unw_regname (reg), *val); - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "%s -> %lx\n", unw_regname (reg), *val); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - ucontext_t *uc = arg; - unw_fpreg_t *addr; - - if (reg < UNW_IA64_FR || reg >= UNW_IA64_FR + 128) - goto badreg; - - addr = tdep_uc_addr (uc, reg, NULL); - if (!addr) - goto badreg; - - if (write) - { - if (ia64_read_only_reg (addr)) - { - Debug (16, "attempt to write read-only register\n"); - return -UNW_EREADONLYREG; - } - *addr = *val; - Debug (12, "%s <- %016lx.%016lx\n", - unw_regname (reg), val->raw.bits[1], val->raw.bits[0]); - } - else - { - *val = *(unw_fpreg_t *) addr; - Debug (12, "%s -> %016lx.%016lx\n", - unw_regname (reg), val->raw.bits[1], val->raw.bits[0]); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - /* attempt to access a non-preserved register */ - return -UNW_EBADREG; -} - -#endif /* !HAVE_SYS_UC_ACCESS_H */ - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp); -} - -HIDDEN void -ia64_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); -#if defined(__linux) - local_addr_space.abi = ABI_LINUX; -#elif defined(__hpux) - local_addr_space.abi = ABI_HPUX; -#endif - local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; - local_addr_space.acc.find_proc_info = tdep_find_proc_info; - local_addr_space.acc.put_unwind_info = put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = ia64_local_resume; - local_addr_space.acc.get_proc_name = get_static_proc_name; - unw_flush_cache (&local_addr_space, 0, 0); -} - -#endif /* !UNW_REMOTE_ONLY */ - -#ifndef UNW_LOCAL_ONLY - -HIDDEN int -ia64_uc_access_reg (struct cursor *c, ia64_loc_t loc, unw_word_t *valp, - int write) -{ -#ifdef HAVE_SYS_UC_ACCESS_H - unw_word_t uc_addr = IA64_GET_AUX_ADDR (loc); - ucontext_t *ucp; - int ret; - - Debug (16, "%s location %s\n", - write ? "writing" : "reading", ia64_strloc (loc)); - - if (c->as == unw_local_addr_space) - ucp = (ucontext_t *) uc_addr; - else - { - unw_word_t *dst, src; - - /* Need to copy-in ucontext_t first. */ - ucp = alloca (sizeof (ucontext_t)); - if (!ucp) - return -UNW_ENOMEM; - - /* For now, there is no non-HP-UX implementation of the - uc_access(3) interface. Because of that, we cannot, e.g., - unwind an HP-UX program from a Linux program. Should that - become possible at some point in the future, the - copy-in/copy-out needs to be adjusted to do byte-swapping if - necessary. */ - assert (c->as->big_endian == (__BYTE_ORDER == __BIG_ENDIAN)); - - dst = (unw_word_t *) ucp; - for (src = uc_addr; src < uc_addr + sizeof (ucontext_t); src += 8) - if ((ret = (*c->as->acc.access_mem) (c->as, src, dst++, 0, c->as_arg)) - < 0) - return ret; - } - - if (IA64_IS_REG_LOC (loc)) - ret = access_reg (unw_local_addr_space, IA64_GET_REG (loc), valp, write, - ucp); - else - { - /* Must be an access to the RSE backing store in ucontext_t. */ - unw_word_t addr = IA64_GET_ADDR (loc); - - if (write) - ret = __uc_set_rsebs (ucp, (uint64_t *) addr, 1, valp); - else - ret = __uc_get_rsebs (ucp, (uint64_t *) addr, 1, valp); - if (ret != 0) - ret = -UNW_EBADREG; - } - if (ret < 0) - return ret; - - if (write && c->as != unw_local_addr_space) - { - /* need to copy-out ucontext_t: */ - unw_word_t dst, *src = (unw_word_t *) ucp; - for (dst = uc_addr; dst < uc_addr + sizeof (ucontext_t); dst += 8) - if ((ret = (*c->as->acc.access_mem) (c->as, dst, src++, 1, c->as_arg)) - < 0) - return ret; - } - return 0; -#else /* !HAVE_SYS_UC_ACCESS_H */ - return -UNW_EINVAL; -#endif /* !HAVE_SYS_UC_ACCESS_H */ -} - -HIDDEN int -ia64_uc_access_fpreg (struct cursor *c, ia64_loc_t loc, unw_fpreg_t *valp, - int write) -{ -#ifdef HAVE_SYS_UC_ACCESS_H - unw_word_t uc_addr = IA64_GET_AUX_ADDR (loc); - ucontext_t *ucp; - int ret; - - if (c->as == unw_local_addr_space) - ucp = (ucontext_t *) uc_addr; - else - { - unw_word_t *dst, src; - - /* Need to copy-in ucontext_t first. */ - ucp = alloca (sizeof (ucontext_t)); - if (!ucp) - return -UNW_ENOMEM; - - /* For now, there is no non-HP-UX implementation of the - uc_access(3) interface. Because of that, we cannot, e.g., - unwind an HP-UX program from a Linux program. Should that - become possible at some point in the future, the - copy-in/copy-out needs to be adjusted to do byte-swapping if - necessary. */ - assert (c->as->big_endian == (__BYTE_ORDER == __BIG_ENDIAN)); - - dst = (unw_word_t *) ucp; - for (src = uc_addr; src < uc_addr + sizeof (ucontext_t); src += 8) - if ((ret = (*c->as->acc.access_mem) (c->as, src, dst++, 0, c->as_arg)) - < 0) - return ret; - } - - if ((ret = access_fpreg (unw_local_addr_space, IA64_GET_REG (loc), valp, - write, ucp)) < 0) - return ret; - - if (write && c->as != unw_local_addr_space) - { - /* need to copy-out ucontext_t: */ - unw_word_t dst, *src = (unw_word_t *) ucp; - for (dst = uc_addr; dst < uc_addr + sizeof (ucontext_t); dst += 8) - if ((ret = (*c->as->acc.access_mem) (c->as, dst, src++, 1, c->as_arg)) - < 0) - return ret; - } - return 0; -#else /* !HAVE_SYS_UC_ACCESS_H */ - return -UNW_EINVAL; -#endif /* !HAVE_SYS_UC_ACCESS_H */ -} - -#endif /* UNW_LOCAL_ONLY */ diff --git a/contrib/libunwind/src/ia64/Ginit_local.c b/contrib/libunwind/src/ia64/Ginit_local.c deleted file mode 100644 index 8c727e1d31f..00000000000 --- a/contrib/libunwind/src/ia64/Ginit_local.c +++ /dev/null @@ -1,110 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2003, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "init.h" -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) -{ - return -UNW_EINVAL; -} - -#else /* !UNW_REMOTE_ONLY */ - -static inline void -set_as_arg (struct cursor *c, unw_context_t *uc) -{ -#if defined(__linux) && defined(__KERNEL__) - c->task = current; - c->as_arg = &uc->sw; -#else - c->as_arg = uc; -#endif -} - -static inline int -get_initial_stack_pointers (struct cursor *c, unw_context_t *uc, - unw_word_t *sp, unw_word_t *bsp) -{ -#if defined(__linux) - unw_word_t sol, bspstore; - -#ifdef __KERNEL__ - sol = (uc->sw.ar_pfs >> 7) & 0x7f; - bspstore = uc->sw.ar_bspstore; - *sp = uc->ksp; -# else - sol = (uc->uc_mcontext.sc_ar_pfs >> 7) & 0x7f; - bspstore = uc->uc_mcontext.sc_ar_bsp; - *sp = uc->uc_mcontext.sc_gr[12]; -# endif - *bsp = rse_skip_regs (bspstore, -sol); -#elif defined(__hpux) - int ret; - - if ((ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_GR + 12), sp)) < 0 - || (ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_AR_BSP), bsp)) < 0) - return ret; -#else -# error Fix me. -#endif - return 0; -} - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t sp, bsp; - int ret; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->as = unw_local_addr_space; - set_as_arg (c, uc); - - if ((ret = get_initial_stack_pointers (c, uc, &sp, &bsp)) < 0) - return ret; - - Debug (4, "initial bsp=%lx, sp=%lx\n", bsp, sp); - - if ((ret = common_init (c, sp, bsp)) < 0) - return ret; - -#ifdef __hpux - /* On HP-UX, the context created by getcontext() points to the - getcontext() system call stub. Step over it: */ - ret = unw_step (cursor); -#endif - return ret; -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/ia64/Ginit_remote.c b/contrib/libunwind/src/ia64/Ginit_remote.c deleted file mode 100644 index e26a4e4b78c..00000000000 --- a/contrib/libunwind/src/ia64/Ginit_remote.c +++ /dev/null @@ -1,61 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002, 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "init.h" -#include "unwind_i.h" - -PROTECTED int -unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) -{ -#ifdef UNW_LOCAL_ONLY - return -UNW_EINVAL; -#else /* !UNW_LOCAL_ONLY */ - struct cursor *c = (struct cursor *) cursor; - unw_word_t sp, bsp; - int ret; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - if (as == unw_local_addr_space) - /* This special-casing is unfortunate and shouldn't be needed; - however, both Linux and HP-UX need to adjust the context a bit - before it's usable. Try to think of a cleaner way of doing - this. Not sure it's possible though, as long as we want to be - able to use the context returned by getcontext() et al. */ - return unw_init_local (cursor, as_arg); - - c->as = as; - c->as_arg = as_arg; - - if ((ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_GR + 12), &sp)) < 0 - || (ret = ia64_get (c, IA64_REG_LOC (c, UNW_IA64_AR_BSP), &bsp)) < 0) - return ret; - - return common_init (c, sp, bsp); -#endif /* !UNW_LOCAL_ONLY */ -} diff --git a/contrib/libunwind/src/ia64/Ginstall_cursor.S b/contrib/libunwind/src/ia64/Ginstall_cursor.S deleted file mode 100644 index 6fb4401faa2..00000000000 --- a/contrib/libunwind/src/ia64/Ginstall_cursor.S +++ /dev/null @@ -1,348 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "ucontext_i.h" - -#ifdef UNW_LOCAL_ONLY -# include "Lcursor_i.h" -# define ia64_install_cursor _ULia64_install_cursor -#else -# include "Gcursor_i.h" -# define ia64_install_cursor _Uia64_install_cursor -#endif - -#define SYS_sigreturn 1181 - -#ifndef UNW_REMOTE_ONLY - -/* ia64_install_cursor (const cursor *c, long pri_unat, long *extra, - long bspstore, long dirty_size, long *dirty_partition, - long dirty_rnat) - - Restores the machine-state represented by C and thereby resumes execution - in that frame. If the frame or one of its descendants was interrupted - by a signal, all registers are restored (including the signal mask). - Otherwise, only the preserved registers, the global-pointer (r1), and - the exception-arguments (r15-r18) are restored. */ - -#define pRet p6 -#define pSig p7 - - .align 32 - .hidden ia64_install_cursor - .global ia64_install_cursor - .proc ia64_install_cursor -ia64_install_cursor: - alloc r3 = ar.pfs, 7, 0, 0, 0 - invala - add r2 = FR_LOC_OFF, in0 - ;; - - ld8 r16 = [r2], LOC_SIZE // r16 = loc[IA64_REG_FR16] - mov.m r10 = ar.rsc // (ar.rsc: ~ 12 cycle latency) - add r3 = FR_LOC_OFF + 16, in0 - ;; - - ld8 r17 = [r2], 2*LOC_SIZE // r17 = loc[IA64_REG_FR17] - ld8 r18 = [r3], 2*LOC_SIZE // r18 = loc[IA64_REG_FR18] - and r16 = -4, r16 - ;; - - ld8 r19 = [r2], 2*LOC_SIZE // r19 = loc[IA64_REG_FR19] - ld8 r20 = [r3], 2*LOC_SIZE // r20 = loc[IA64_REG_FR20] - and r17 = -4, r17 - ;; - - ldf.fill f16 = [r16] // f16 restored (don't touch no more) - ldf.fill f17 = [r17] // f17 restored (don't touch no more) - and r18 = -4, r18 - - ld8 r21 = [r2], 2*LOC_SIZE // r21 = loc[IA64_REG_FR21] - ld8 r22 = [r3], 2*LOC_SIZE // r22 = loc[IA64_REG_FR22] - and r19 = -4, r19 - ;; - - ldf.fill f18 = [r18] // f18 restored (don't touch no more) - ldf.fill f19 = [r19] // f19 restored (don't touch no more) - and r20 = -4, r20 - - ld8 r23 = [r2], 2*LOC_SIZE // r23 = loc[IA64_REG_FR23] - ld8 r24 = [r3], 2*LOC_SIZE // r24 = loc[IA64_REG_FR24] - and r21 = -4, r21 - ;; - - ldf.fill f20 = [r20] // f20 restored (don't touch no more) - ldf.fill f21 = [r21] // f21 restored (don't touch no more) - and r22 = -4, r22 - - ld8 r25 = [r2], 2*LOC_SIZE // r25 = loc[IA64_REG_FR25] - ld8 r26 = [r3], 2*LOC_SIZE // r26 = loc[IA64_REG_FR26] - and r23 = -4, r23 - ;; - - ldf.fill f22 = [r22] // f22 restored (don't touch no more) - ldf.fill f23 = [r23] // f23 restored (don't touch no more) - and r24 = -4, r24 - - ld8 r27 = [r2], 2*LOC_SIZE // r27 = loc[IA64_REG_FR27] - ld8 r28 = [r3], 2*LOC_SIZE // r28 = loc[IA64_REG_FR28] - and r25 = -4, r25 - ;; - - ldf.fill f24 = [r24] // f24 restored (don't touch no more) - ldf.fill f25 = [r25] // f25 restored (don't touch no more) - and r26 = -4, r26 - - ld8 r29 = [r2], 2*LOC_SIZE // r29 = loc[IA64_REG_FR29] - ld8 r30 = [r3], 2*LOC_SIZE // r30 = loc[IA64_REG_FR30] - and r27 = -4, r27 - ;; - - ldf.fill f26 = [r26] // f26 restored (don't touch no more) - ldf.fill f27 = [r27] // f27 restored (don't touch no more) - and r28 = -4, r28 - - ld8 r31 = [r2] // r31 = loc[IA64_REG_FR31] - mov.m ar.unat = in1 - and r29 = -4, r29 - ;; - - ldf.fill f28 = [r28] // f28 restored (don't touch no more) - ldf.fill f29 = [r29] // f29 restored (don't touch no more) - and r30 = -4, r30 - - ld8 r1 = [in2], 8 // gp restored (don't touch no more) - add r8 = SIGCONTEXT_ADDR_OFF, in0 - and r31 = -4, r31 - ;; - - ld8 r8 = [r8] // r8 = sigcontext_addr - and r11 = 0x1c, r10 // clear all but rsc.be and rsc.pl - add r2 = PFS_LOC_OFF, in0 - - ldf.fill f30 = [r30] // f30 restored (don't touch no more) - ldf.fill f31 = [r31] // f31 restored (don't touch no more) - add r3 = 8, in2 - ;; - - ld8.fill r4 = [in2], 16 // r4 restored (don't touch no more) - ld8.fill r5 = [r3], 16 // r5 restored (don't touch no more) - cmp.eq pRet, pSig = r0, r8 // sigcontext_addr == NULL? - ;; - ld8.fill r6 = [in2], 16 // r6 restored (don't touch no more) - ld8.fill r7 = [r3] // r7 restored (don't touch no more) - add r3 = IP_OFF, in0 - ;; - - ld8 r14 = [r2], (B1_LOC_OFF - PFS_LOC_OFF) // r14 = pfs_loc - ld8 r15 = [r3] // r15 = ip - add r3 = (B2_LOC_OFF - IP_OFF), r3 - ;; - - ld8 r16 = [r2], (B3_LOC_OFF - B1_LOC_OFF) // r16 = b1_loc - ld8 r17= [r3], (B4_LOC_OFF - B2_LOC_OFF) // r17 = b2_loc - and r14 = -4, r14 - ;; - - ld8 r18 = [r2], (B5_LOC_OFF - B3_LOC_OFF) // r18 = b3_loc - ld8 r19 = [r3], (F2_LOC_OFF - B4_LOC_OFF) // r19 = b4_loc - and r16 = -4, r16 - ;; - - ld8 r20 = [r2], (F3_LOC_OFF - B5_LOC_OFF) // r20 = b5_loc - ld8 r21 = [r3], (F4_LOC_OFF - F2_LOC_OFF) // r21 = f2_loc - and r17 = -4, r17 - ;; - - ld8 r16 = [r16] // r16 = *b1_loc - ld8 r17 = [r17] // r17 = *b2_loc - and r18 = -4, r18 - - ld8 r22 = [r2], (F5_LOC_OFF - F3_LOC_OFF) // r21 = f3_loc - ld8 r23 = [r3], (UNAT_LOC_OFF - F4_LOC_OFF) // r22 = f4_loc - and r19 = -4, r19 - ;; - - ld8 r18 = [r18] // r18 = *b3_loc - ld8 r19 = [r19] // r19 = *b4_loc - and r20 = -4, r20 - - ld8 r24 = [r2], (LC_LOC_OFF - F5_LOC_OFF) // r24 = f5_loc - ld8 r25 = [r3], (FPSR_LOC_OFF - UNAT_LOC_OFF) // r25 = unat_loc - and r21 = -4, r21 - ;; - - and r22 = -4, r22 - and r23 = -4, r23 - and r24 = -4, r24 - - ld8 r20 = [r20] // r20 = *b5_loc - ldf.fill f2 = [r21] // f2 restored (don't touch no more) - mov b1 = r16 // b1 restored (don't touch no more) - ;; - - ldf.fill f3 = [r22] // f3 restored (don't touch no more) - ldf.fill f4 = [r23] // f4 restored (don't touch no more) - mov b2 = r17 // b2 restored (don't touch no more) - - ld8 r26 = [r2], (RNAT_LOC_OFF - LC_LOC_OFF) // r26 = lc_loc - ld8 r27 = [r3] // r27 = fpsr_loc - and r25 = -4, r25 - - add r3 = (PSP_OFF - FPSR_LOC_OFF), r3 - nop 0 - nop 0 - ;; - - ldf.fill f5 = [r24] // f5 restored (don't touch no more) -(pRet) ld8 r25 = [r25] // r25 = *unat_loc - mov b3 = r18 // b3 restored (don't touch no more) - - ld8 r28 = [r2], (BSP_OFF - RNAT_LOC_OFF) // r28 = rnat_loc - ld8 r29 = [r3], (PR_OFF - PSP_OFF) // r29 = sp - mov b4 = r19 // b4 restored (don't touch no more) - - and r26 = -4, r26 - and r27 = -4, r27 - mov b5 = r20 // b5 restored (don't touch no more) - ;; - - ld8 r26 = [r26] // r26 = *lc_loc - ld8 r27 = [r27] // r27 = *fpsr_loc - and r28 = -4, r28 - - mov r30 = in3 // make backup-copy of new bsp - ld8 r31 = [r3] // r31 = pr - mov rp = r15 - ;; - - ld8 r28 = [r28] // r28 = rnat - mov.m ar.rsc = r11 // put RSE into enforced lazy mode - mov.i ar.lc = r26 // lc restored (don't touch no more) - ;; - - loadrs // drop dirty partition - mov r9 = in2 // make backup-copy of &extra[r16] - cmp.eq p8, p0 = in4, r0 // dirty-size == 0? -(p8) br.cond.dpnt.many .skip_load_dirty - - mov r2 = in4 // make backup-copy of dirty_size - mov r15 = in5 // make backup-copy of dirty_partition - mov r16 = in6 // make backup-copy of dirty_rnat - ;; - - alloc r3 = ar.pfs, 0, 0, 0, 0 // drop register frame - dep r11 = r2, r11, 16, 16 - ;; - mov.m ar.bspstore = r15 - ;; - mov.m ar.rnat = r16 - mov.m ar.rsc = r11 // 14 cycles latency to loadrs - ;; - loadrs // loadup new dirty partition - ;; - -.skip_load_dirty: - mov.m ar.bspstore = r30 // restore register backing-store - add r3 = 8, r9 // r3 = &extra[r16] - ;; - -(pRet) mov.m ar.fpsr = r27 // fpsr restored (don't touch no more) - mov.m ar.rnat = r28 -(pSig) br.cond.dpnt.many .next - -/****** Return via br.ret: */ - - ld8 r14 = [r14] // r14 = *pfs_loc - ld8 r15 = [r9], 16 // r15 restored (don't touch no more) - mov pr = r31, -1 // pr restored (don't touch no more) - ;; - - ld8 r16 = [r3], 16 // r16 restored (don't touch no more) - ld8 r17 = [r9] // r17 restored (don't touch no more) - nop.i 0 - ;; - - ld8 r18 = [r3] // r18 restored (don't touch no more) - mov.m ar.rsc = r10 // restore original ar.rsc - mov sp = r29 - - mov.m ar.unat = r25 // unat restored (don't touch no more) - mov.i ar.pfs = r14 - br.ret.sptk.many rp - ;; - -/****** Return via sigreturn(): */ - -.next: mov.m ar.rsc = r10 // restore original ar.rsc - add r2 = (SC_FR + 6*16), r8 - add r3 = (SC_FR + 7*16), r8 - ;; - - ldf.fill f6 = [r2], 32 - ldf.fill f7 = [r3], 32 - nop 0 - ;; - - ldf.fill f8 = [r2], 32 - ldf.fill f9 = [r3], 32 - nop 0 - ;; - - ldf.fill f10 = [r2], 32 - ldf.fill f11 = [r3], 32 - nop 0 - ;; - - ldf.fill f12 = [r2], 32 - ldf.fill f13 = [r3], 32 - nop 0 - ;; - - ldf.fill f14 = [r2], 32 - ldf.fill f15 = [r3], 32 - mov sp = r29 - ;; - -#if NEW_SYSCALL - add r2 = 8, tp;; - ld8 r2 = [r2] - mov r15 = SYS_sigreturn - mov b7 = r2 - br.call.sptk.many b6 = b7 - ;; -#else - mov r15 = SYS_sigreturn - break 0x100000 -#endif - break 0 // bug out if sigreturn() returns - - .endp ia64_install_cursor - -#endif /* !UNW_REMOTE_ONLY */ -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ia64/Gis_signal_frame.c b/contrib/libunwind/src/ia64/Gis_signal_frame.c deleted file mode 100644 index 0b7e19cbf98..00000000000 --- a/contrib/libunwind/src/ia64/Gis_signal_frame.c +++ /dev/null @@ -1,54 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - struct ia64_state_record sr; - int ret; - - /* Crude and slow, but we need to peek ahead into the unwind - descriptors to find out if the current IP is inside the signal - trampoline. */ - ret = ia64_fetch_proc_info (c, c->ip, 1); - if (ret < 0) - return ret; - - ret = ia64_create_state_record (c, &sr); - if (ret < 0) - return ret; - - /* For now, we assume that any non-zero abi marker implies a signal frame. - This should get us pretty far. */ - ret = (sr.abi_marker != 0); - - ia64_free_state_record (&sr); - - Debug (1, "(cursor=%p, ip=0x%016lx) -> %d\n", c, c->ip, ret); - return ret; -} diff --git a/contrib/libunwind/src/ia64/Gparser.c b/contrib/libunwind/src/ia64/Gparser.c deleted file mode 100644 index b1f0f4a1182..00000000000 --- a/contrib/libunwind/src/ia64/Gparser.c +++ /dev/null @@ -1,1131 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -/* forward declaration: */ -static int create_state_record_for (struct cursor *c, - struct ia64_state_record *sr, - unw_word_t ip); - -typedef unsigned long unw_word; - -#define alloc_reg_state() (mempool_alloc (&unw.reg_state_pool)) -#define free_reg_state(rs) (mempool_free (&unw.reg_state_pool, rs)) -#define alloc_labeled_state() (mempool_alloc (&unw.labeled_state_pool)) -#define free_labeled_state(s) (mempool_free (&unw.labeled_state_pool, s)) - -/* Routines to manipulate the state stack. */ - -static inline void -push (struct ia64_state_record *sr) -{ - struct ia64_reg_state *rs; - - rs = alloc_reg_state (); - if (!rs) - { - print_error ("libunwind: cannot stack reg state!\n"); - return; - } - memcpy (rs, &sr->curr, sizeof (*rs)); - sr->curr.next = rs; -} - -static void -pop (struct ia64_state_record *sr) -{ - struct ia64_reg_state *rs = sr->curr.next; - - if (!rs) - { - print_error ("libunwind: stack underflow!\n"); - return; - } - memcpy (&sr->curr, rs, sizeof (*rs)); - free_reg_state (rs); -} - -/* Make a copy of the state stack. Non-recursive to avoid stack overflows. */ -static struct ia64_reg_state * -dup_state_stack (struct ia64_reg_state *rs) -{ - struct ia64_reg_state *copy, *prev = NULL, *first = NULL; - - while (rs) - { - copy = alloc_reg_state (); - if (!copy) - { - print_error ("unwind.dup_state_stack: out of memory\n"); - return NULL; - } - memcpy (copy, rs, sizeof (*copy)); - if (first) - prev->next = copy; - else - first = copy; - rs = rs->next; - prev = copy; - } - return first; -} - -/* Free all stacked register states (but not RS itself). */ -static void -free_state_stack (struct ia64_reg_state *rs) -{ - struct ia64_reg_state *p, *next; - - for (p = rs->next; p != NULL; p = next) - { - next = p->next; - free_reg_state (p); - } - rs->next = NULL; -} - -/* Unwind decoder routines */ - -static enum ia64_pregnum CONST_ATTR -decode_abreg (unsigned char abreg, int memory) -{ - switch (abreg) - { - case 0x04 ... 0x07: - return IA64_REG_R4 + (abreg - 0x04); - case 0x22 ... 0x25: - return IA64_REG_F2 + (abreg - 0x22); - case 0x30 ... 0x3f: - return IA64_REG_F16 + (abreg - 0x30); - case 0x41 ... 0x45: - return IA64_REG_B1 + (abreg - 0x41); - case 0x60: - return IA64_REG_PR; - case 0x61: - return IA64_REG_PSP; - case 0x62: - return memory ? IA64_REG_PRI_UNAT_MEM : IA64_REG_PRI_UNAT_GR; - case 0x63: - return IA64_REG_IP; - case 0x64: - return IA64_REG_BSP; - case 0x65: - return IA64_REG_BSPSTORE; - case 0x66: - return IA64_REG_RNAT; - case 0x67: - return IA64_REG_UNAT; - case 0x68: - return IA64_REG_FPSR; - case 0x69: - return IA64_REG_PFS; - case 0x6a: - return IA64_REG_LC; - default: - break; - } - Dprintf ("libunwind: bad abreg=0x%x\n", abreg); - return IA64_REG_LC; -} - -static void -set_reg (struct ia64_reg_info *reg, enum ia64_where where, int when, - unsigned long val) -{ - reg->val = val; - reg->where = where; - if (reg->when == IA64_WHEN_NEVER) - reg->when = when; -} - -static void -alloc_spill_area (unsigned long *offp, unsigned long regsize, - struct ia64_reg_info *lo, struct ia64_reg_info *hi) -{ - struct ia64_reg_info *reg; - - for (reg = hi; reg >= lo; --reg) - { - if (reg->where == IA64_WHERE_SPILL_HOME) - { - reg->where = IA64_WHERE_PSPREL; - *offp -= regsize; - reg->val = *offp; - } - } -} - -static inline void -spill_next_when (struct ia64_reg_info **regp, struct ia64_reg_info *lim, - unw_word t) -{ - struct ia64_reg_info *reg; - - for (reg = *regp; reg <= lim; ++reg) - { - if (reg->where == IA64_WHERE_SPILL_HOME) - { - reg->when = t; - *regp = reg + 1; - return; - } - } - Dprintf ("libunwind: excess spill!\n"); -} - -static inline void -finish_prologue (struct ia64_state_record *sr) -{ - struct ia64_reg_info *reg; - unsigned long off; - int i; - - /* First, resolve implicit register save locations (see Section - "11.4.2.3 Rules for Using Unwind Descriptors", rule 3). */ - for (i = 0; i < (int) ARRAY_SIZE (unw.save_order); ++i) - { - reg = sr->curr.reg + unw.save_order[i]; - if (reg->where == IA64_WHERE_GR_SAVE) - { - reg->where = IA64_WHERE_GR; - reg->val = sr->gr_save_loc++; - } - } - - /* Next, compute when the fp, general, and branch registers get - saved. This must come before alloc_spill_area() because we need - to know which registers are spilled to their home locations. */ - - if (sr->imask) - { - unsigned char kind, mask = 0, *cp = sr->imask; - unsigned long t; - static const unsigned char limit[3] = - { - IA64_REG_F31, IA64_REG_R7, IA64_REG_B5 - }; - struct ia64_reg_info *(regs[3]); - - regs[0] = sr->curr.reg + IA64_REG_F2; - regs[1] = sr->curr.reg + IA64_REG_R4; - regs[2] = sr->curr.reg + IA64_REG_B1; - - for (t = 0; (int) t < sr->region_len; ++t) - { - if ((t & 3) == 0) - mask = *cp++; - kind = (mask >> 2 * (3 - (t & 3))) & 3; - if (kind > 0) - spill_next_when (®s[kind - 1], sr->curr.reg + limit[kind - 1], - sr->region_start + t); - } - } - - /* Next, lay out the memory stack spill area. */ - - if (sr->any_spills) - { - off = sr->spill_offset; - alloc_spill_area (&off, 16, sr->curr.reg + IA64_REG_F2, - sr->curr.reg + IA64_REG_F31); - alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_B1, - sr->curr.reg + IA64_REG_B5); - alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_R4, - sr->curr.reg + IA64_REG_R7); - } -} - -/* Region header descriptors. */ - -static void -desc_prologue (int body, unw_word rlen, unsigned char mask, - unsigned char grsave, struct ia64_state_record *sr) -{ - int i, region_start; - - if (!(sr->in_body || sr->first_region)) - finish_prologue (sr); - sr->first_region = 0; - - /* check if we're done: */ - if (sr->when_target < sr->region_start + sr->region_len) - { - sr->done = 1; - return; - } - - region_start = sr->region_start + sr->region_len; - - for (i = 0; i < sr->epilogue_count; ++i) - pop (sr); - sr->epilogue_count = 0; - sr->when_sp_restored = IA64_WHEN_NEVER; - - sr->region_start = region_start; - sr->region_len = rlen; - sr->in_body = body; - - if (!body) - { - push (sr); - - if (mask) - for (i = 0; i < 4; ++i) - { - if (mask & 0x8) - set_reg (sr->curr.reg + unw.save_order[i], IA64_WHERE_GR, - sr->region_start + sr->region_len - 1, grsave++); - mask <<= 1; - } - sr->gr_save_loc = grsave; - sr->any_spills = 0; - sr->imask = 0; - sr->spill_offset = 0x10; /* default to psp+16 */ - } -} - -/* Prologue descriptors. */ - -static inline void -desc_abi (unsigned char abi, unsigned char context, - struct ia64_state_record *sr) -{ - sr->abi_marker = (abi << 8) | context; -} - -static inline void -desc_br_gr (unsigned char brmask, unsigned char gr, - struct ia64_state_record *sr) -{ - int i; - - for (i = 0; i < 5; ++i) - { - if (brmask & 1) - set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_GR, - sr->region_start + sr->region_len - 1, gr++); - brmask >>= 1; - } -} - -static inline void -desc_br_mem (unsigned char brmask, struct ia64_state_record *sr) -{ - int i; - - for (i = 0; i < 5; ++i) - { - if (brmask & 1) - { - set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_SPILL_HOME, - sr->region_start + sr->region_len - 1, 0); - sr->any_spills = 1; - } - brmask >>= 1; - } -} - -static inline void -desc_frgr_mem (unsigned char grmask, unw_word frmask, - struct ia64_state_record *sr) -{ - int i; - - for (i = 0; i < 4; ++i) - { - if ((grmask & 1) != 0) - { - set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME, - sr->region_start + sr->region_len - 1, 0); - sr->any_spills = 1; - } - grmask >>= 1; - } - for (i = 0; i < 20; ++i) - { - if ((frmask & 1) != 0) - { - int base = (i < 4) ? IA64_REG_F2 : IA64_REG_F16 - 4; - set_reg (sr->curr.reg + base + i, IA64_WHERE_SPILL_HOME, - sr->region_start + sr->region_len - 1, 0); - sr->any_spills = 1; - } - frmask >>= 1; - } -} - -static inline void -desc_fr_mem (unsigned char frmask, struct ia64_state_record *sr) -{ - int i; - - for (i = 0; i < 4; ++i) - { - if ((frmask & 1) != 0) - { - set_reg (sr->curr.reg + IA64_REG_F2 + i, IA64_WHERE_SPILL_HOME, - sr->region_start + sr->region_len - 1, 0); - sr->any_spills = 1; - } - frmask >>= 1; - } -} - -static inline void -desc_gr_gr (unsigned char grmask, unsigned char gr, - struct ia64_state_record *sr) -{ - int i; - - for (i = 0; i < 4; ++i) - { - if ((grmask & 1) != 0) - set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_GR, - sr->region_start + sr->region_len - 1, gr++); - grmask >>= 1; - } -} - -static inline void -desc_gr_mem (unsigned char grmask, struct ia64_state_record *sr) -{ - int i; - - for (i = 0; i < 4; ++i) - { - if ((grmask & 1) != 0) - { - set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME, - sr->region_start + sr->region_len - 1, 0); - sr->any_spills = 1; - } - grmask >>= 1; - } -} - -static inline void -desc_mem_stack_f (unw_word t, unw_word size, struct ia64_state_record *sr) -{ - set_reg (sr->curr.reg + IA64_REG_PSP, IA64_WHERE_NONE, - sr->region_start + MIN ((int) t, sr->region_len - 1), 16 * size); -} - -static inline void -desc_mem_stack_v (unw_word t, struct ia64_state_record *sr) -{ - sr->curr.reg[IA64_REG_PSP].when = - sr->region_start + MIN ((int) t, sr->region_len - 1); -} - -static inline void -desc_reg_gr (unsigned char reg, unsigned char dst, - struct ia64_state_record *sr) -{ - set_reg (sr->curr.reg + reg, IA64_WHERE_GR, - sr->region_start + sr->region_len - 1, dst); -} - -static inline void -desc_reg_psprel (unsigned char reg, unw_word pspoff, - struct ia64_state_record *sr) -{ - set_reg (sr->curr.reg + reg, IA64_WHERE_PSPREL, - sr->region_start + sr->region_len - 1, 0x10 - 4 * pspoff); -} - -static inline void -desc_reg_sprel (unsigned char reg, unw_word spoff, - struct ia64_state_record *sr) -{ - set_reg (sr->curr.reg + reg, IA64_WHERE_SPREL, - sr->region_start + sr->region_len - 1, 4 * spoff); -} - -static inline void -desc_rp_br (unsigned char dst, struct ia64_state_record *sr) -{ - sr->return_link_reg = dst; -} - -static inline void -desc_reg_when (unsigned char regnum, unw_word t, struct ia64_state_record *sr) -{ - struct ia64_reg_info *reg = sr->curr.reg + regnum; - - if (reg->where == IA64_WHERE_NONE) - reg->where = IA64_WHERE_GR_SAVE; - reg->when = sr->region_start + MIN ((int) t, sr->region_len - 1); -} - -static inline void -desc_spill_base (unw_word pspoff, struct ia64_state_record *sr) -{ - sr->spill_offset = 0x10 - 4 * pspoff; -} - -static inline unsigned char * -desc_spill_mask (unsigned char *imaskp, struct ia64_state_record *sr) -{ - sr->imask = imaskp; - return imaskp + (2 * sr->region_len + 7) / 8; -} - -/* Body descriptors. */ - -static inline void -desc_epilogue (unw_word t, unw_word ecount, struct ia64_state_record *sr) -{ - sr->when_sp_restored = sr->region_start + sr->region_len - 1 - t; - sr->epilogue_count = ecount + 1; -} - -static inline void -desc_copy_state (unw_word label, struct ia64_state_record *sr) -{ - struct ia64_labeled_state *ls; - - for (ls = sr->labeled_states; ls; ls = ls->next) - { - if (ls->label == label) - { - free_state_stack (&sr->curr); - memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr)); - sr->curr.next = dup_state_stack (ls->saved_state.next); - return; - } - } - print_error ("libunwind: failed to find labeled state\n"); -} - -static inline void -desc_label_state (unw_word label, struct ia64_state_record *sr) -{ - struct ia64_labeled_state *ls; - - ls = alloc_labeled_state (); - if (!ls) - { - print_error ("unwind.desc_label_state(): out of memory\n"); - return; - } - ls->label = label; - memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state)); - ls->saved_state.next = dup_state_stack (sr->curr.next); - - /* insert into list of labeled states: */ - ls->next = sr->labeled_states; - sr->labeled_states = ls; -} - -/* General descriptors. */ - -static inline int -desc_is_active (unsigned char qp, unw_word t, struct ia64_state_record *sr) -{ - if (sr->when_target <= sr->region_start + MIN ((int) t, sr->region_len - 1)) - return 0; - if (qp > 0) - { - if ((sr->pr_val & ((unw_word_t) 1 << qp)) == 0) - return 0; - sr->pr_mask |= ((unw_word_t) 1 << qp); - } - return 1; -} - -static inline void -desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg, - struct ia64_state_record *sr) -{ - struct ia64_reg_info *r; - - if (!desc_is_active (qp, t, sr)) - return; - - r = sr->curr.reg + decode_abreg (abreg, 0); - r->where = IA64_WHERE_NONE; - r->when = IA64_WHEN_NEVER; - r->val = 0; -} - -static inline void -desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg, - unsigned char x, unsigned char ytreg, - struct ia64_state_record *sr) -{ - enum ia64_where where = IA64_WHERE_GR; - struct ia64_reg_info *r; - - if (!desc_is_active (qp, t, sr)) - return; - - if (x) - where = IA64_WHERE_BR; - else if (ytreg & 0x80) - where = IA64_WHERE_FR; - - r = sr->curr.reg + decode_abreg (abreg, 0); - r->where = where; - r->when = sr->region_start + MIN ((int) t, sr->region_len - 1); - r->val = (ytreg & 0x7f); -} - -static inline void -desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg, - unw_word pspoff, struct ia64_state_record *sr) -{ - struct ia64_reg_info *r; - - if (!desc_is_active (qp, t, sr)) - return; - - r = sr->curr.reg + decode_abreg (abreg, 1); - r->where = IA64_WHERE_PSPREL; - r->when = sr->region_start + MIN ((int) t, sr->region_len - 1); - r->val = 0x10 - 4 * pspoff; -} - -static inline void -desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, - unw_word spoff, struct ia64_state_record *sr) -{ - struct ia64_reg_info *r; - - if (!desc_is_active (qp, t, sr)) - return; - - r = sr->curr.reg + decode_abreg (abreg, 1); - r->where = IA64_WHERE_SPREL; - r->when = sr->region_start + MIN ((int) t, sr->region_len - 1); - r->val = 4 * spoff; -} - -#define UNW_DEC_BAD_CODE(code) \ - print_error ("libunwind: unknown code encountered\n") - -/* Register names. */ -#define UNW_REG_BSP IA64_REG_BSP -#define UNW_REG_BSPSTORE IA64_REG_BSPSTORE -#define UNW_REG_FPSR IA64_REG_FPSR -#define UNW_REG_LC IA64_REG_LC -#define UNW_REG_PFS IA64_REG_PFS -#define UNW_REG_PR IA64_REG_PR -#define UNW_REG_RNAT IA64_REG_RNAT -#define UNW_REG_PSP IA64_REG_PSP -#define UNW_REG_RP IA64_REG_IP -#define UNW_REG_UNAT IA64_REG_UNAT - -/* Region headers. */ -#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg) desc_prologue(0,r,m,gr,arg) -#define UNW_DEC_PROLOGUE(fmt,b,r,arg) desc_prologue(b,r,0,32,arg) - -/* Prologue descriptors. */ -#define UNW_DEC_ABI(fmt,a,c,arg) desc_abi(a,c,arg) -#define UNW_DEC_BR_GR(fmt,b,g,arg) desc_br_gr(b,g,arg) -#define UNW_DEC_BR_MEM(fmt,b,arg) desc_br_mem(b,arg) -#define UNW_DEC_FRGR_MEM(fmt,g,f,arg) desc_frgr_mem(g,f,arg) -#define UNW_DEC_FR_MEM(fmt,f,arg) desc_fr_mem(f,arg) -#define UNW_DEC_GR_GR(fmt,m,g,arg) desc_gr_gr(m,g,arg) -#define UNW_DEC_GR_MEM(fmt,m,arg) desc_gr_mem(m,arg) -#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg) desc_mem_stack_f(t,s,arg) -#define UNW_DEC_MEM_STACK_V(fmt,t,arg) desc_mem_stack_v(t,arg) -#define UNW_DEC_REG_GR(fmt,r,d,arg) desc_reg_gr(r,d,arg) -#define UNW_DEC_REG_PSPREL(fmt,r,o,arg) desc_reg_psprel(r,o,arg) -#define UNW_DEC_REG_SPREL(fmt,r,o,arg) desc_reg_sprel(r,o,arg) -#define UNW_DEC_REG_WHEN(fmt,r,t,arg) desc_reg_when(r,t,arg) -#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) \ - desc_reg_when(IA64_REG_PRI_UNAT_GR,t,arg) -#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) \ - desc_reg_when(IA64_REG_PRI_UNAT_MEM,t,arg) -#define UNW_DEC_PRIUNAT_GR(fmt,r,arg) \ - desc_reg_gr(IA64_REG_PRI_UNAT_GR,r,arg) -#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) \ - desc_reg_psprel(IA64_REG_PRI_UNAT_MEM,o,arg) -#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) \ - desc_reg_sprel(IA64_REG_PRI_UNAT_MEM,o,arg) -#define UNW_DEC_RP_BR(fmt,d,arg) desc_rp_br(d,arg) -#define UNW_DEC_SPILL_BASE(fmt,o,arg) desc_spill_base(o,arg) -#define UNW_DEC_SPILL_MASK(fmt,m,arg) (m = desc_spill_mask(m,arg)) - -/* Body descriptors. */ -#define UNW_DEC_EPILOGUE(fmt,t,c,arg) desc_epilogue(t,c,arg) -#define UNW_DEC_COPY_STATE(fmt,l,arg) desc_copy_state(l,arg) -#define UNW_DEC_LABEL_STATE(fmt,l,arg) desc_label_state(l,arg) - -/* General unwind descriptors. */ -#define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg) desc_spill_reg_p(p,t,a,x,y,arg) -#define UNW_DEC_SPILL_REG(f,t,a,x,y,arg) desc_spill_reg_p(0,t,a,x,y,arg) -#define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg) \ - desc_spill_psprel_p(p,t,a,o,arg) -#define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg) \ - desc_spill_psprel_p(0,t,a,o,arg) -#define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg) desc_spill_sprel_p(p,t,a,o,arg) -#define UNW_DEC_SPILL_SPREL(f,t,a,o,arg) desc_spill_sprel_p(0,t,a,o,arg) -#define UNW_DEC_RESTORE_P(f,p,t,a,arg) desc_restore_p(p,t,a,arg) -#define UNW_DEC_RESTORE(f,t,a,arg) desc_restore_p(0,t,a,arg) - -#include "unwind_decoder.h" - -#ifdef _U_dyn_op - -/* parse dynamic unwind info */ - -static struct ia64_reg_info * -lookup_preg (int regnum, int memory, struct ia64_state_record *sr) -{ - int preg; - - switch (regnum) - { - case UNW_IA64_AR_BSP: preg = IA64_REG_BSP; break; - case UNW_IA64_AR_BSPSTORE: preg = IA64_REG_BSPSTORE; break; - case UNW_IA64_AR_FPSR: preg = IA64_REG_FPSR; break; - case UNW_IA64_AR_LC: preg = IA64_REG_LC; break; - case UNW_IA64_AR_PFS: preg = IA64_REG_PFS; break; - case UNW_IA64_AR_RNAT: preg = IA64_REG_RNAT; break; - case UNW_IA64_AR_UNAT: preg = IA64_REG_UNAT; break; - case UNW_IA64_BR + 0: preg = IA64_REG_IP; break; - case UNW_IA64_PR: preg = IA64_REG_PR; break; - case UNW_IA64_SP: preg = IA64_REG_PSP; break; - - case UNW_IA64_NAT: - if (memory) - preg = IA64_REG_PRI_UNAT_MEM; - else - preg = IA64_REG_PRI_UNAT_GR; - break; - - case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7: - preg = IA64_REG_R4 + (regnum - (UNW_IA64_GR + 4)); - break; - - case UNW_IA64_BR + 1 ... UNW_IA64_BR + 5: - preg = IA64_REG_B1 + (regnum - UNW_IA64_BR); - break; - - case UNW_IA64_FR + 2 ... UNW_IA64_FR + 5: - preg = IA64_REG_F2 + (regnum - (UNW_IA64_FR + 2)); - break; - - case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31: - preg = IA64_REG_F16 + (regnum - (UNW_IA64_FR + 16)); - break; - - default: - Dprintf ("%s: invalid register number %d\n", __FUNCTION__, regnum); - return NULL; - } - return sr->curr.reg + preg; -} - -/* An alias directive inside a region of length RLEN is interpreted to - mean that the region behaves exactly like the first RLEN - instructions at the aliased IP. RLEN=0 implies that the current - state matches exactly that of before the instruction at the aliased - IP is executed. */ - -static int -desc_alias (unw_dyn_op_t *op, struct cursor *c, struct ia64_state_record *sr) -{ - struct ia64_state_record orig_sr = *sr; - int i, ret, when, rlen = sr->region_len; - unw_word_t new_ip; - - when = MIN (sr->when_target, rlen); - new_ip = op->val + ((when / 3) * 16 + (when % 3)); - - if ((ret = ia64_fetch_proc_info (c, new_ip, 1)) < 0) - return ret; - - if ((ret = create_state_record_for (c, sr, new_ip)) < 0) - return ret; - - sr->first_region = orig_sr.first_region; - sr->done = 0; - sr->any_spills |= orig_sr.any_spills; - sr->in_body = orig_sr.in_body; - sr->region_start = orig_sr.region_start; - sr->region_len = orig_sr.region_len; - if (sr->when_sp_restored != IA64_WHEN_NEVER) - sr->when_sp_restored = op->when + MIN (orig_sr.when_sp_restored, rlen); - sr->epilogue_count = orig_sr.epilogue_count; - sr->when_target = orig_sr.when_target; - - for (i = 0; i < IA64_NUM_PREGS; ++i) - if (sr->curr.reg[i].when != IA64_WHEN_NEVER) - sr->curr.reg[i].when = op->when + MIN (sr->curr.reg[i].when, rlen); - - ia64_free_state_record (sr); - sr->labeled_states = orig_sr.labeled_states; - sr->curr.next = orig_sr.curr.next; - return 0; -} - -static inline int -parse_dynamic (struct cursor *c, struct ia64_state_record *sr) -{ - unw_dyn_info_t *di = c->pi.unwind_info; - unw_dyn_proc_info_t *proc = &di->u.pi; - unw_dyn_region_info_t *r; - struct ia64_reg_info *ri; - enum ia64_where where; - int32_t when, len; - unw_dyn_op_t *op; - unw_word_t val; - int memory, ret; - int8_t qp; - - for (r = proc->regions; r; r = r->next) - { - len = r->insn_count; - if (len < 0) - { - if (r->next) - { - Debug (1, "negative region length allowed in last region only!"); - return -UNW_EINVAL; - } - len = -len; - /* hack old region info to set the start where we need it: */ - sr->region_start = (di->end_ip - di->start_ip) / 0x10 * 3 - len; - sr->region_len = 0; - } - /* all regions are treated as prologue regions: */ - desc_prologue (0, len, 0, 0, sr); - - if (sr->done) - return 0; - - for (op = r->op; op < r->op + r->op_count; ++op) - { - when = op->when; - val = op->val; - qp = op->qp; - - if (!desc_is_active (qp, when, sr)) - continue; - - when = sr->region_start + MIN ((int) when, sr->region_len - 1); - - switch (op->tag) - { - case UNW_DYN_SAVE_REG: - memory = 0; - if ((unsigned) (val - UNW_IA64_GR) < 128) - where = IA64_WHERE_GR; - else if ((unsigned) (val - UNW_IA64_FR) < 128) - where = IA64_WHERE_FR; - else if ((unsigned) (val - UNW_IA64_BR) < 8) - where = IA64_WHERE_BR; - else - { - Dprintf ("%s: can't save to register number %d\n", - __FUNCTION__, (int) op->reg); - return -UNW_EBADREG; - } - /* fall through */ - update_reg_info: - ri = lookup_preg (op->reg, memory, sr); - if (!ri) - return -UNW_EBADREG; - ri->where = where; - ri->when = when; - ri->val = val; - break; - - case UNW_DYN_SPILL_FP_REL: - memory = 1; - where = IA64_WHERE_PSPREL; - val = 0x10 - val; - goto update_reg_info; - - case UNW_DYN_SPILL_SP_REL: - memory = 1; - where = IA64_WHERE_SPREL; - goto update_reg_info; - - case UNW_DYN_ADD: - if (op->reg == UNW_IA64_SP) - { - if (val & 0xf) - { - Dprintf ("%s: frame-size %ld not an integer " - "multiple of 16\n", - __FUNCTION__, (long) op->val); - return -UNW_EINVAL; - } - desc_mem_stack_f (when, -((int64_t) val / 16), sr); - } - else - { - Dprintf ("%s: can only ADD to stack-pointer\n", - __FUNCTION__); - return -UNW_EBADREG; - } - break; - - case UNW_DYN_POP_FRAMES: - sr->when_sp_restored = when; - sr->epilogue_count = op->val; - break; - - case UNW_DYN_LABEL_STATE: - desc_label_state (op->val, sr); - break; - - case UNW_DYN_COPY_STATE: - desc_copy_state (op->val, sr); - break; - - case UNW_DYN_ALIAS: - if ((ret = desc_alias (op, c, sr)) < 0) - return ret; - - case UNW_DYN_STOP: - goto end_of_ops; - } - } - end_of_ops: - ; - } - return 0; -} -#else -# define parse_dynamic(c,sr) (-UNW_EINVAL) -#endif /* _U_dyn_op */ - - -HIDDEN int -ia64_fetch_proc_info (struct cursor *c, unw_word_t ip, int need_unwind_info) -{ - int ret, dynamic = 1; - - if (c->pi_valid && !need_unwind_info) - return 0; - - /* check dynamic info first --- it overrides everything else */ - ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info, - c->as_arg); - if (ret == -UNW_ENOINFO) - { - dynamic = 0; - ret = ia64_find_proc_info (c, ip, need_unwind_info); - } - - c->pi_valid = 1; - c->pi_is_dynamic = dynamic; - return ret; -} - -static inline void -put_unwind_info (struct cursor *c, unw_proc_info_t *pi) -{ - if (!c->pi_valid) - return; - - if (c->pi_is_dynamic) - unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg); - else - ia64_put_unwind_info (c, pi); -} - -static int -create_state_record_for (struct cursor *c, struct ia64_state_record *sr, - unw_word_t ip) -{ - unw_word_t predicates = c->pr; - struct ia64_reg_info *r; - uint8_t *dp, *desc_end; - int ret; - - assert (c->pi_valid); - - /* build state record */ - memset (sr, 0, sizeof (*sr)); - for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r) - r->when = IA64_WHEN_NEVER; - sr->pr_val = predicates; - sr->first_region = 1; - - if (!c->pi.unwind_info) - { - /* No info, return default unwinder (leaf proc, no mem stack, no - saved regs), rp in b0, pfs in ar.pfs. */ - Debug (1, "no unwind info for ip=0x%lx (gp=%lx)\n", - (long) ip, (long) c->pi.gp); - sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR; - sr->curr.reg[IA64_REG_IP].when = -1; - sr->curr.reg[IA64_REG_IP].val = 0; - goto out; - } - - sr->when_target = (3 * ((ip & ~(unw_word_t) 0xf) - c->pi.start_ip) / 16 - + (ip & 0xf)); - - switch (c->pi.format) - { - case UNW_INFO_FORMAT_TABLE: - case UNW_INFO_FORMAT_REMOTE_TABLE: - dp = c->pi.unwind_info; - desc_end = dp + c->pi.unwind_info_size; - while (!sr->done && dp < desc_end) - dp = unw_decode (dp, sr->in_body, sr); - ret = 0; - break; - - case UNW_INFO_FORMAT_DYNAMIC: - ret = parse_dynamic (c, sr); - break; - - default: - ret = -UNW_EINVAL; - } - - put_unwind_info (c, &c->pi); - - if (ret < 0) - return ret; - - if (sr->when_target > sr->when_sp_restored) - { - /* sp has been restored and all values on the memory stack below - psp also have been restored. */ - sr->curr.reg[IA64_REG_PSP].val = 0; - sr->curr.reg[IA64_REG_PSP].where = IA64_WHERE_NONE; - sr->curr.reg[IA64_REG_PSP].when = IA64_WHEN_NEVER; - for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r) - if ((r->where == IA64_WHERE_PSPREL && r->val <= 0x10) - || r->where == IA64_WHERE_SPREL) - { - r->val = 0; - r->where = IA64_WHERE_NONE; - r->when = IA64_WHEN_NEVER; - } - } - - /* If RP did't get saved, generate entry for the return link - register. */ - if (sr->curr.reg[IA64_REG_IP].when >= sr->when_target) - { - sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR; - sr->curr.reg[IA64_REG_IP].when = -1; - sr->curr.reg[IA64_REG_IP].val = sr->return_link_reg; - } - - if (sr->when_target > sr->curr.reg[IA64_REG_BSP].when - && sr->when_target > sr->curr.reg[IA64_REG_BSPSTORE].when - && sr->when_target > sr->curr.reg[IA64_REG_RNAT].when) - { - Debug (8, "func 0x%lx may switch the register-backing-store\n", - c->pi.start_ip); - c->pi.flags |= UNW_PI_FLAG_IA64_RBS_SWITCH; - } - out: -#if UNW_DEBUG - if (unwi_debug_level > 2) - { - Dprintf ("%s: state record for func 0x%lx, t=%u (flags=0x%lx):\n", - __FUNCTION__, - (long) c->pi.start_ip, sr->when_target, (long) c->pi.flags); - for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r) - { - if (r->where != IA64_WHERE_NONE || r->when != IA64_WHEN_NEVER) - { - Dprintf (" %s <- ", unw.preg_name[r - sr->curr.reg]); - switch (r->where) - { - case IA64_WHERE_GR: - Dprintf ("r%lu", (long) r->val); - break; - case IA64_WHERE_FR: - Dprintf ("f%lu", (long) r->val); - break; - case IA64_WHERE_BR: - Dprintf ("b%lu", (long) r->val); - break; - case IA64_WHERE_SPREL: - Dprintf ("[sp+0x%lx]", (long) r->val); - break; - case IA64_WHERE_PSPREL: - Dprintf ("[psp+0x%lx]", (long) r->val); - break; - case IA64_WHERE_NONE: - Dprintf ("%s+0x%lx", - unw.preg_name[r - sr->curr.reg], (long) r->val); - break; - default: - Dprintf ("BADWHERE(%d)", r->where); - break; - } - Dprintf ("\t\t%d\n", r->when); - } - } - } -#endif - return 0; -} - -/* The proc-info must be valid for IP before this routine can be - called. */ -HIDDEN int -ia64_create_state_record (struct cursor *c, struct ia64_state_record *sr) -{ - return create_state_record_for (c, sr, c->ip); -} - -HIDDEN int -ia64_free_state_record (struct ia64_state_record *sr) -{ - struct ia64_labeled_state *ls, *next; - - /* free labeled register states & stack: */ - - for (ls = sr->labeled_states; ls; ls = next) - { - next = ls->next; - free_state_stack (&ls->saved_state); - free_labeled_state (ls); - } - free_state_stack (&sr->curr); - - return 0; -} - -HIDDEN int -ia64_make_proc_info (struct cursor *c) -{ - int ret, caching = c->as->caching_policy != UNW_CACHE_NONE; - - if (!caching || ia64_get_cached_proc_info (c) < 0) - { - /* Lookup it up the slow way... */ - if ((ret = ia64_fetch_proc_info (c, c->ip, 0)) < 0) - return ret; - if (caching) - ia64_cache_proc_info (c); - } - return 0; -} diff --git a/contrib/libunwind/src/ia64/Grbs.c b/contrib/libunwind/src/ia64/Grbs.c deleted file mode 100644 index e7c01fe219e..00000000000 --- a/contrib/libunwind/src/ia64/Grbs.c +++ /dev/null @@ -1,319 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Logically, we like to think of the stack as a contiguous region of -memory. Unfortunately, this logical view doesn't work for the -register backing store, because the RSE is an asynchronous engine and -because UNIX/Linux allow for stack-switching via sigaltstack(2). -Specifically, this means that any given stacked register may or may -not be backed up by memory in the current stack. If not, then the -backing memory may be found in any of the "more inner" (younger) -stacks. The routines in this file help manage the discontiguous -nature of the register backing store. The routines are completely -independent of UNIX/Linux, but each stack frame that switches the -backing store is expected to reserve 4 words for use by libunwind. For -example, in the Linux sigcontext, sc_fr[0] and sc_fr[1] serve this -purpose. */ - -#include "unwind_i.h" - -#if UNW_DEBUG - -HIDDEN const char * -ia64_strloc (ia64_loc_t loc) -{ - static char buf[128]; - - if (IA64_IS_NULL_LOC (loc)) - return ""; - - buf[0] = '\0'; - - if (IA64_IS_MEMSTK_NAT (loc)) - strcat (buf, "memstk_nat("); - if (IA64_IS_UC_LOC (loc)) - strcat (buf, "uc("); - if (IA64_IS_FP_LOC (loc)) - strcat (buf, "fp("); - - if (IA64_IS_REG_LOC (loc)) - sprintf (buf + strlen (buf), "%s", unw_regname (IA64_GET_REG (loc))); - else - sprintf (buf + strlen (buf), "0x%llx", - (unsigned long long) IA64_GET_ADDR (loc)); - - if (IA64_IS_FP_LOC (loc)) - strcat (buf, ")"); - if (IA64_IS_UC_LOC (loc)) - strcat (buf, ")"); - if (IA64_IS_MEMSTK_NAT (loc)) - strcat (buf, ")"); - - return buf; -} - -#endif /* UNW_DEBUG */ - -HIDDEN int -rbs_switch (struct cursor *c, - unw_word_t saved_bsp, unw_word_t saved_bspstore, - ia64_loc_t saved_rnat_loc) -{ - struct rbs_area *rbs = &c->rbs_area[c->rbs_curr]; - unw_word_t lo, ndirty, rbs_base; - int ret; - - Debug (10, "(left=%u, curr=%u)\n", c->rbs_left_edge, c->rbs_curr); - - /* Calculate address "lo" at which the backing store starts: */ - ndirty = rse_num_regs (saved_bspstore, saved_bsp); - lo = rse_skip_regs (c->bsp, -ndirty); - - rbs->size = (rbs->end - lo); - - /* If the previously-recorded rbs-area is empty we don't need to - track it and we can simply overwrite it... */ - if (rbs->size) - { - Debug (10, "inner=[0x%lx-0x%lx)\n", - (long) (rbs->end - rbs->size), (long) rbs->end); - - c->rbs_curr = (c->rbs_curr + 1) % ARRAY_SIZE (c->rbs_area); - rbs = c->rbs_area + c->rbs_curr; - - if (c->rbs_curr == c->rbs_left_edge) - c->rbs_left_edge = (c->rbs_left_edge + 1) % ARRAY_SIZE (c->rbs_area); - } - - if ((ret = rbs_get_base (c, saved_bspstore, &rbs_base)) < 0) - return ret; - - rbs->end = saved_bspstore; - rbs->size = saved_bspstore - rbs_base; - rbs->rnat_loc = saved_rnat_loc; - - c->bsp = saved_bsp; - - Debug (10, "outer=[0x%llx-0x%llx), rnat@%s\n", (long long) rbs_base, - (long long) rbs->end, ia64_strloc (rbs->rnat_loc)); - return 0; -} - -HIDDEN int -rbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip, - ia64_loc_t *locp, ia64_loc_t *rnat_locp) -{ - unw_word_t nregs, bsp = c->bsp, curr = c->rbs_curr, n; - unw_word_t left_edge = c->rbs_left_edge; -#if UNW_DEBUG - int reg = 32 + regs_to_skip; -#endif - - while (!rbs_contains (&c->rbs_area[curr], bsp)) - { - if (curr == left_edge) - { - Debug (1, "could not find register r%d!\n", reg); - return -UNW_EBADREG; - } - - n = rse_num_regs (c->rbs_area[curr].end, bsp); - curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) % ARRAY_SIZE (c->rbs_area); - bsp = rse_skip_regs (c->rbs_area[curr].end - c->rbs_area[curr].size, n); - } - - while (1) - { - nregs = rse_num_regs (bsp, c->rbs_area[curr].end); - - if (regs_to_skip < nregs) - { - /* found it: */ - unw_word_t addr; - - addr = rse_skip_regs (bsp, regs_to_skip); - if (locp) - *locp = rbs_loc (c->rbs_area + curr, addr); - if (rnat_locp) - *rnat_locp = rbs_get_rnat_loc (c->rbs_area + curr, addr); - return 0; - } - - if (curr == left_edge) - { - Debug (1, "could not find register r%d!\n", reg); - return -UNW_EBADREG; - } - - regs_to_skip -= nregs; - - curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) % ARRAY_SIZE (c->rbs_area); - bsp = c->rbs_area[curr].end - c->rbs_area[curr].size; - } -} - -#ifdef NEED_RBS_COVER_AND_FLUSH - -static inline int -get_rnat (struct cursor *c, struct rbs_area *rbs, unw_word_t bsp, - unw_word_t *__restrict rnatp) -{ - ia64_loc_t rnat_locp = rbs_get_rnat_loc (rbs, bsp); - - return ia64_get (c, rnat_locp, rnatp); -} - -/* Simulate the effect of "cover" followed by a "flushrs" for the - target-frame. However, since the target-frame's backing store - may not have space for the registers that got spilled onto other - rbs-areas, we save those registers to DIRTY_PARTITION where - we can then load them via a single "loadrs". - - This function returns the size of the dirty-partition that was - created or a negative error-code in case of error. - - Note: This does not modify the rbs_area[] structure in any way. */ -HIDDEN int -rbs_cover_and_flush (struct cursor *c, unw_word_t nregs, - unw_word_t *dirty_partition, unw_word_t *dirty_rnat, - unw_word_t *bspstore) -{ - unw_word_t n, src_mask, dst_mask, bsp, *dst, src_rnat, dst_rnat = 0; - unw_word_t curr = c->rbs_curr, left_edge = c->rbs_left_edge; - struct rbs_area *rbs = c->rbs_area + curr; - int ret; - - bsp = c->bsp; - c->bsp = rse_skip_regs (bsp, nregs); - - if (likely (rbs_contains (rbs, bsp))) - { - /* at least _some_ registers are on rbs... */ - n = rse_num_regs (bsp, rbs->end); - if (likely (n >= nregs)) - { - /* common case #1: all registers are on current rbs... */ - /* got lucky: _all_ registers are on rbs... */ - ia64_loc_t rnat_loc = rbs_get_rnat_loc (rbs, c->bsp); - - *bspstore = c->bsp; - - if (IA64_IS_REG_LOC (rnat_loc)) - { - unw_word_t rnat_addr = (unw_word_t) - tdep_uc_addr (c->as_arg, UNW_IA64_AR_RNAT, NULL); - rnat_loc = IA64_LOC_ADDR (rnat_addr, 0); - } - c->loc[IA64_REG_RNAT] = rnat_loc; - return 0; /* all done */ - } - nregs -= n; /* account for registers already on the rbs */ - - assert (rse_skip_regs (c->bsp, -nregs) == rse_skip_regs (rbs->end, 0)); - } - else - /* Earlier frames also didn't get spilled; need to "loadrs" those, - too... */ - nregs += rse_num_regs (rbs->end, bsp); - - /* OK, we need to copy NREGS registers to the dirty partition. */ - - *bspstore = bsp = rbs->end; - c->loc[IA64_REG_RNAT] = rbs->rnat_loc; - assert (!IA64_IS_REG_LOC (rbs->rnat_loc)); - - dst = dirty_partition; - - while (nregs > 0) - { - if (unlikely (!rbs_contains (rbs, bsp))) - { - /* switch to next non-empty rbs-area: */ - do - { - if (curr == left_edge) - { - Debug (0, "rbs-underflow while flushing %lu regs, " - "bsp=0x%lx, dst=0x%p\n", (unsigned long) nregs, - (unsigned long) bsp, dst); - return -UNW_EBADREG; - } - - assert (rse_num_regs (rbs->end, bsp) == 0); - - curr = (curr + ARRAY_SIZE (c->rbs_area) - 1) - % ARRAY_SIZE (c->rbs_area); - rbs = c->rbs_area + curr; - bsp = rbs->end - rbs->size; - } - while (rbs->size == 0); - - if ((ret = get_rnat (c, rbs, bsp, &src_rnat)) < 0) - return ret; - } - - if (unlikely (rse_is_rnat_slot (bsp))) - { - bsp += 8; - if ((ret = get_rnat (c, rbs, bsp, &src_rnat)) < 0) - return ret; - } - if (unlikely (rse_is_rnat_slot ((unw_word_t) dst))) - { - *dst++ = dst_rnat; - dst_rnat = 0; - } - - src_mask = ((unw_word_t) 1) << rse_slot_num (bsp); - dst_mask = ((unw_word_t) 1) << rse_slot_num ((unw_word_t) dst); - - if (src_rnat & src_mask) - dst_rnat |= dst_mask; - else - dst_rnat &= ~dst_mask; - - /* copy one slot: */ - if ((ret = ia64_get (c, rbs_loc (rbs, bsp), dst)) < 0) - return ret; - - /* advance to next slot: */ - --nregs; - bsp += 8; - ++dst; - } - if (unlikely (rse_is_rnat_slot ((unw_word_t) dst))) - { - /* The LOADRS instruction loads "the N bytes below the current - BSP" but BSP can never point to an RNaT slot so if the last - destination word happens to be an RNaT slot, we need to write - that slot now. */ - *dst++ = dst_rnat; - dst_rnat = 0; - } - *dirty_rnat = dst_rnat; - return (char *) dst - (char *) dirty_partition; -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/ia64/Greg_states_iterate.c b/contrib/libunwind/src/ia64/Greg_states_iterate.c deleted file mode 100644 index 49908b2cab2..00000000000 --- a/contrib/libunwind/src/ia64/Greg_states_iterate.c +++ /dev/null @@ -1,39 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - // Needs dwarf support on ia64 - // return dwarf_reg_states_iterate (&c->dwarf, cb, token); - return -UNW_EINVAL; -} diff --git a/contrib/libunwind/src/ia64/Gregs.c b/contrib/libunwind/src/ia64/Gregs.c deleted file mode 100644 index ac6f738a6cd..00000000000 --- a/contrib/libunwind/src/ia64/Gregs.c +++ /dev/null @@ -1,612 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "offsets.h" -#include "regs.h" -#include "unwind_i.h" - -static inline ia64_loc_t -linux_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr) -{ -#if !defined(UNW_LOCAL_ONLY) || defined(__linux) - unw_word_t addr = c->sigcontext_addr, flags, tmp_addr; - int i; - - if (ia64_get_abi_marker (c) == ABI_MARKER_LINUX_SIGTRAMP - || ia64_get_abi_marker (c) == ABI_MARKER_OLD_LINUX_SIGTRAMP) - { - switch (reg) - { - case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3: - case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31: - /* Linux sigcontext contains the NaT bit of scratch register - N in bit position N of the sc_nat member. */ - *nat_bitnr = (reg - UNW_IA64_NAT); - addr += LINUX_SC_NAT_OFF; - break; - - case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3: - case UNW_IA64_GR + 8 ... UNW_IA64_GR + 31: - addr += LINUX_SC_GR_OFF + 8 * (reg - UNW_IA64_GR); - break; - - case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15: - addr += LINUX_SC_FR_OFF + 16 * (reg - UNW_IA64_FR); - return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP); - - case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127: - if (ia64_get (c, IA64_LOC_ADDR (addr + LINUX_SC_FLAGS_OFF, 0), - &flags) < 0) - return IA64_NULL_LOC; - - if (!(flags & IA64_SC_FLAG_FPH_VALID)) - { - /* initialize fph partition: */ - tmp_addr = addr + LINUX_SC_FR_OFF + 32*16; - for (i = 32; i < 128; ++i, tmp_addr += 16) - if (ia64_putfp (c, IA64_LOC_ADDR (tmp_addr, 0), - unw.read_only.f0) < 0) - return IA64_NULL_LOC; - /* mark fph partition as valid: */ - if (ia64_put (c, IA64_LOC_ADDR (addr + LINUX_SC_FLAGS_OFF, 0), - flags | IA64_SC_FLAG_FPH_VALID) < 0) - return IA64_NULL_LOC; - } - - addr += LINUX_SC_FR_OFF + 16 * (reg - UNW_IA64_FR); - return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP); - - case UNW_IA64_BR + 0: addr += LINUX_SC_BR_OFF + 0; break; - case UNW_IA64_BR + 6: addr += LINUX_SC_BR_OFF + 6*8; break; - case UNW_IA64_BR + 7: addr += LINUX_SC_BR_OFF + 7*8; break; - case UNW_IA64_AR_RSC: addr += LINUX_SC_AR_RSC_OFF; break; - case UNW_IA64_AR_CSD: addr += LINUX_SC_AR_CSD_OFF; break; - case UNW_IA64_AR_SSD: addr += LINUX_SC_AR_SSD_OFF; break; - case UNW_IA64_AR_CCV: addr += LINUX_SC_AR_CCV; break; - - default: - if (unw_is_fpreg (reg)) - return IA64_FPREG_LOC (c, reg); - else - return IA64_REG_LOC (c, reg); - } - return IA64_LOC_ADDR (addr, 0); - } - else - { - int is_nat = 0; - - if ((unsigned) (reg - UNW_IA64_NAT) < 128) - { - is_nat = 1; - reg -= (UNW_IA64_NAT - UNW_IA64_GR); - } - if (ia64_get_abi_marker (c) == ABI_MARKER_LINUX_INTERRUPT) - { - switch (reg) - { - case UNW_IA64_BR + 6 ... UNW_IA64_BR + 7: - addr += LINUX_PT_B6_OFF + 8 * (reg - (UNW_IA64_BR + 6)); - break; - - case UNW_IA64_AR_CSD: addr += LINUX_PT_CSD_OFF; break; - case UNW_IA64_AR_SSD: addr += LINUX_PT_SSD_OFF; break; - - case UNW_IA64_GR + 8 ... UNW_IA64_GR + 11: - addr += LINUX_PT_R8_OFF + 8 * (reg - (UNW_IA64_GR + 8)); - break; - - case UNW_IA64_IP: addr += LINUX_PT_IIP_OFF; break; - case UNW_IA64_CFM: addr += LINUX_PT_IFS_OFF; break; - case UNW_IA64_AR_UNAT: addr += LINUX_PT_UNAT_OFF; break; - case UNW_IA64_AR_PFS: addr += LINUX_PT_PFS_OFF; break; - case UNW_IA64_AR_RSC: addr += LINUX_PT_RSC_OFF; break; - case UNW_IA64_AR_RNAT: addr += LINUX_PT_RNAT_OFF; break; - case UNW_IA64_AR_BSPSTORE: addr += LINUX_PT_BSPSTORE_OFF; break; - case UNW_IA64_PR: addr += LINUX_PT_PR_OFF; break; - case UNW_IA64_BR + 0: addr += LINUX_PT_B0_OFF; break; - - case UNW_IA64_GR + 1: - /* The saved r1 value is valid only in the frame in which - it was saved; for everything else we need to look up - the appropriate gp value. */ - if (c->sigcontext_addr != c->sp + 0x10) - return IA64_NULL_LOC; - addr += LINUX_PT_R1_OFF; - break; - - case UNW_IA64_GR + 12: addr += LINUX_PT_R12_OFF; break; - case UNW_IA64_GR + 13: addr += LINUX_PT_R13_OFF; break; - case UNW_IA64_AR_FPSR: addr += LINUX_PT_FPSR_OFF; break; - case UNW_IA64_GR + 15: addr += LINUX_PT_R15_OFF; break; - case UNW_IA64_GR + 14: addr += LINUX_PT_R14_OFF; break; - case UNW_IA64_GR + 2: addr += LINUX_PT_R2_OFF; break; - case UNW_IA64_GR + 3: addr += LINUX_PT_R3_OFF; break; - - case UNW_IA64_GR + 16 ... UNW_IA64_GR + 31: - addr += LINUX_PT_R16_OFF + 8 * (reg - (UNW_IA64_GR + 16)); - break; - - case UNW_IA64_AR_CCV: addr += LINUX_PT_CCV_OFF; break; - - case UNW_IA64_FR + 6 ... UNW_IA64_FR + 11: - addr += LINUX_PT_F6_OFF + 16 * (reg - (UNW_IA64_FR + 6)); - return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP); - - default: - if (unw_is_fpreg (reg)) - return IA64_FPREG_LOC (c, reg); - else - return IA64_REG_LOC (c, reg); - } - } - else if (ia64_get_abi_marker (c) == ABI_MARKER_OLD_LINUX_INTERRUPT) - { - switch (reg) - { - case UNW_IA64_GR + 1: - /* The saved r1 value is valid only in the frame in which - it was saved; for everything else we need to look up - the appropriate gp value. */ - if (c->sigcontext_addr != c->sp + 0x10) - return IA64_NULL_LOC; - addr += LINUX_OLD_PT_R1_OFF; - break; - - case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3: - addr += LINUX_OLD_PT_R2_OFF + 8 * (reg - (UNW_IA64_GR + 2)); - break; - - case UNW_IA64_GR + 8 ... UNW_IA64_GR + 11: - addr += LINUX_OLD_PT_R8_OFF + 8 * (reg - (UNW_IA64_GR + 8)); - break; - - case UNW_IA64_GR + 16 ... UNW_IA64_GR + 31: - addr += LINUX_OLD_PT_R16_OFF + 8 * (reg - (UNW_IA64_GR + 16)); - break; - - case UNW_IA64_FR + 6 ... UNW_IA64_FR + 9: - addr += LINUX_OLD_PT_F6_OFF + 16 * (reg - (UNW_IA64_FR + 6)); - return IA64_LOC_ADDR (addr, IA64_LOC_TYPE_FP); - - case UNW_IA64_BR + 0: addr += LINUX_OLD_PT_B0_OFF; break; - case UNW_IA64_BR + 6: addr += LINUX_OLD_PT_B6_OFF; break; - case UNW_IA64_BR + 7: addr += LINUX_OLD_PT_B7_OFF; break; - - case UNW_IA64_AR_RSC: addr += LINUX_OLD_PT_RSC_OFF; break; - case UNW_IA64_AR_CCV: addr += LINUX_OLD_PT_CCV_OFF; break; - - default: - if (unw_is_fpreg (reg)) - return IA64_FPREG_LOC (c, reg); - else - return IA64_REG_LOC (c, reg); - } - } - if (is_nat) - { - /* For Linux pt-regs structure, bit number is determined by - the UNaT slot number (as determined by st8.spill) and the - bits are saved wherever the (primary) UNaT was saved. */ - *nat_bitnr = ia64_unat_slot_num (addr); - return c->loc[IA64_REG_PRI_UNAT_MEM]; - } - return IA64_LOC_ADDR (addr, 0); - } -#endif - return IA64_NULL_LOC; -} - -static inline ia64_loc_t -hpux_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr) -{ -#if !defined(UNW_LOCAL_ONLY) || defined(__hpux) - return IA64_LOC_UC_REG (reg, c->sigcontext_addr); -#else - return IA64_NULL_LOC; -#endif -} - -HIDDEN ia64_loc_t -ia64_scratch_loc (struct cursor *c, unw_regnum_t reg, uint8_t *nat_bitnr) -{ - if (c->sigcontext_addr) - { - if (ia64_get_abi (c) == ABI_LINUX) - return linux_scratch_loc (c, reg, nat_bitnr); - else if (ia64_get_abi (c) == ABI_HPUX) - return hpux_scratch_loc (c, reg, nat_bitnr); - else - return IA64_NULL_LOC; - } - else - return IA64_REG_LOC (c, reg); -} - -static inline int -update_nat (struct cursor *c, ia64_loc_t nat_loc, unw_word_t mask, - unw_word_t *valp, int write) -{ - unw_word_t nat_word; - int ret; - - ret = ia64_get (c, nat_loc, &nat_word); - if (ret < 0) - return ret; - - if (write) - { - if (*valp) - nat_word |= mask; - else - nat_word &= ~mask; - ret = ia64_put (c, nat_loc, nat_word); - } - else - *valp = (nat_word & mask) != 0; - return ret; -} - -static int -access_nat (struct cursor *c, - ia64_loc_t nat_loc, ia64_loc_t reg_loc, uint8_t nat_bitnr, - unw_word_t *valp, int write) -{ - unw_word_t mask = 0; - unw_fpreg_t tmp; - int ret; - - if (IA64_IS_FP_LOC (reg_loc)) - { - /* NaT bit is saved as a NaTVal. This happens when a general - register is saved to a floating-point register. */ - if (write) - { - if (*valp) - { - if (ia64_is_big_endian (c)) - ret = ia64_putfp (c, reg_loc, unw.nat_val_be); - else - ret = ia64_putfp (c, reg_loc, unw.nat_val_le); - } - else - { - unw_word_t *src, *dst; - unw_fpreg_t tmp; - - ret = ia64_getfp (c, reg_loc, &tmp); - if (ret < 0) - return ret; - - /* Reset the exponent to 0x1003e so that the significand - will be interpreted as an integer value. */ - src = (unw_word_t *) &unw.int_val_be; - dst = (unw_word_t *) &tmp; - if (!ia64_is_big_endian (c)) - ++src, ++dst; - *dst = *src; - - ret = ia64_putfp (c, reg_loc, tmp); - } - } - else - { - ret = ia64_getfp (c, reg_loc, &tmp); - if (ret < 0) - return ret; - - if (ia64_is_big_endian (c)) - *valp = (memcmp (&tmp, &unw.nat_val_be, sizeof (tmp)) == 0); - else - *valp = (memcmp (&tmp, &unw.nat_val_le, sizeof (tmp)) == 0); - } - return ret; - } - - if ((IA64_IS_REG_LOC (nat_loc) - && (unsigned) (IA64_GET_REG (nat_loc) - UNW_IA64_NAT) < 128) - || IA64_IS_UC_LOC (reg_loc)) - { - if (write) - return ia64_put (c, nat_loc, *valp); - else - return ia64_get (c, nat_loc, valp); - } - - if (IA64_IS_NULL_LOC (nat_loc)) - { - /* NaT bit is not saved. This happens if a general register is - saved to a branch register. Since the NaT bit gets lost, we - need to drop it here, too. Note that if the NaT bit had been - set when the save occurred, it would have caused a NaT - consumption fault. */ - if (write) - { - if (*valp) - return -UNW_EBADREG; /* can't set NaT bit */ - } - else - *valp = 0; - return 0; - } - - mask = (unw_word_t) 1 << nat_bitnr; - return update_nat (c, nat_loc, mask, valp, write); -} - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - ia64_loc_t loc, reg_loc, nat_loc; - unw_word_t mask, val; - uint8_t nat_bitnr; - int ret; - - switch (reg) - { - /* frame registers: */ - - case UNW_IA64_BSP: - if (write) - c->bsp = *valp; - else - *valp = c->bsp; - return 0; - - case UNW_REG_SP: - if (write) - c->sp = *valp; - else - *valp = c->sp; - return 0; - - case UNW_REG_IP: - if (write) - { - c->ip = *valp; /* also update the IP cache */ - if (c->pi_valid && (*valp < c->pi.start_ip || *valp >= c->pi.end_ip)) - c->pi_valid = 0; /* new IP outside of current proc */ - } - loc = c->loc[IA64_REG_IP]; - break; - - /* preserved registers: */ - - case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7: - loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_GR + 4))]; - break; - - case UNW_IA64_NAT + 4 ... UNW_IA64_NAT + 7: - loc = c->loc[IA64_REG_NAT4 + (reg - (UNW_IA64_NAT + 4))]; - reg_loc = c->loc[IA64_REG_R4 + (reg - (UNW_IA64_NAT + 4))]; - nat_bitnr = c->nat_bitnr[reg - (UNW_IA64_NAT + 4)]; - return access_nat (c, loc, reg_loc, nat_bitnr, valp, write); - - case UNW_IA64_AR_BSP: loc = c->loc[IA64_REG_BSP]; break; - case UNW_IA64_AR_BSPSTORE: loc = c->loc[IA64_REG_BSPSTORE]; break; - case UNW_IA64_AR_PFS: loc = c->loc[IA64_REG_PFS]; break; - case UNW_IA64_AR_RNAT: loc = c->loc[IA64_REG_RNAT]; break; - case UNW_IA64_AR_UNAT: loc = c->loc[IA64_REG_UNAT]; break; - case UNW_IA64_AR_LC: loc = c->loc[IA64_REG_LC]; break; - case UNW_IA64_AR_FPSR: loc = c->loc[IA64_REG_FPSR]; break; - case UNW_IA64_BR + 1: loc = c->loc[IA64_REG_B1]; break; - case UNW_IA64_BR + 2: loc = c->loc[IA64_REG_B2]; break; - case UNW_IA64_BR + 3: loc = c->loc[IA64_REG_B3]; break; - case UNW_IA64_BR + 4: loc = c->loc[IA64_REG_B4]; break; - case UNW_IA64_BR + 5: loc = c->loc[IA64_REG_B5]; break; - - case UNW_IA64_CFM: - if (write) - c->cfm = *valp; /* also update the CFM cache */ - loc = c->cfm_loc; - break; - - case UNW_IA64_PR: - /* - * Note: broad-side access to the predicates is NOT rotated - * (i.e., it is done as if CFM.rrb.pr == 0. - */ - if (write) - { - c->pr = *valp; /* update the predicate cache */ - return ia64_put (c, c->loc[IA64_REG_PR], *valp); - } - else - return ia64_get (c, c->loc[IA64_REG_PR], valp); - - case UNW_IA64_GR + 32 ... UNW_IA64_GR + 127: /* stacked reg */ - reg = rotate_gr (c, reg - UNW_IA64_GR); - if (reg < 0) - return -UNW_EBADREG; - ret = ia64_get_stacked (c, reg, &loc, NULL); - if (ret < 0) - return ret; - break; - - case UNW_IA64_NAT + 32 ... UNW_IA64_NAT + 127: /* stacked reg */ - reg = rotate_gr (c, reg - UNW_IA64_NAT); - if (reg < 0) - return -UNW_EBADREG; - ret = ia64_get_stacked (c, reg, &loc, &nat_loc); - if (ret < 0) - return ret; - assert (!IA64_IS_REG_LOC (loc)); - mask = (unw_word_t) 1 << rse_slot_num (IA64_GET_ADDR (loc)); - return update_nat (c, nat_loc, mask, valp, write); - - case UNW_IA64_AR_EC: - if ((ret = ia64_get (c, c->ec_loc, &val)) < 0) - return ret; - - if (write) - { - val = ((val & ~((unw_word_t) 0x3f << 52)) | ((*valp & 0x3f) << 52)); - return ia64_put (c, c->ec_loc, val); - } - else - { - *valp = (val >> 52) & 0x3f; - return 0; - } - - /* scratch & special registers: */ - - case UNW_IA64_GR + 0: - if (write) - return -UNW_EREADONLYREG; - *valp = 0; - return 0; - - case UNW_IA64_NAT + 0: - if (write) - return -UNW_EREADONLYREG; - *valp = 0; - return 0; - - case UNW_IA64_NAT + 1: - case UNW_IA64_NAT + 2 ... UNW_IA64_NAT + 3: - case UNW_IA64_NAT + 8 ... UNW_IA64_NAT + 31: - loc = ia64_scratch_loc (c, reg, &nat_bitnr); - if (IA64_IS_NULL_LOC (loc) && reg == UNW_IA64_NAT + 1) - { - /* access to GP */ - if (write) - return -UNW_EREADONLYREG; - *valp = 0; - return 0; - } - if (!(IA64_IS_REG_LOC (loc) || IA64_IS_UC_LOC (loc) - || IA64_IS_FP_LOC (loc))) - /* We're dealing with a NaT bit stored in memory. */ - return update_nat(c, loc, (unw_word_t) 1 << nat_bitnr, valp, write); - break; - - case UNW_IA64_GR + 15 ... UNW_IA64_GR + 18: - mask = 1 << (reg - (UNW_IA64_GR + 15)); - if (write) - { - c->eh_args[reg - (UNW_IA64_GR + 15)] = *valp; - c->eh_valid_mask |= mask; - return 0; - } - else if ((c->eh_valid_mask & mask) != 0) - { - *valp = c->eh_args[reg - (UNW_IA64_GR + 15)]; - return 0; - } - else - loc = ia64_scratch_loc (c, reg, NULL); - break; - - case UNW_IA64_GR + 1: /* global pointer */ - case UNW_IA64_GR + 2 ... UNW_IA64_GR + 3: - case UNW_IA64_GR + 8 ... UNW_IA64_GR + 14: - case UNW_IA64_GR + 19 ... UNW_IA64_GR + 31: - case UNW_IA64_BR + 0: - case UNW_IA64_BR + 6: - case UNW_IA64_BR + 7: - case UNW_IA64_AR_RSC: - case UNW_IA64_AR_CSD: - case UNW_IA64_AR_SSD: - case UNW_IA64_AR_CCV: - loc = ia64_scratch_loc (c, reg, NULL); - if (IA64_IS_NULL_LOC (loc) && reg == UNW_IA64_GR + 1) - { - /* access to GP */ - if (write) - return -UNW_EREADONLYREG; - - /* ensure c->pi is up-to-date: */ - if ((ret = ia64_make_proc_info (c)) < 0) - return ret; - *valp = c->pi.gp; - return 0; - } - break; - - default: - Debug (1, "bad register number %d\n", reg); - return -UNW_EBADREG; - } - - if (write) - return ia64_put (c, loc, *valp); - else - return ia64_get (c, loc, valp); -} - -HIDDEN int -tdep_access_fpreg (struct cursor *c, int reg, unw_fpreg_t *valp, - int write) -{ - ia64_loc_t loc; - - switch (reg) - { - case UNW_IA64_FR + 0: - if (write) - return -UNW_EREADONLYREG; - *valp = unw.read_only.f0; - return 0; - - case UNW_IA64_FR + 1: - if (write) - return -UNW_EREADONLYREG; - - if (ia64_is_big_endian (c)) - *valp = unw.read_only.f1_be; - else - *valp = unw.read_only.f1_le; - return 0; - - case UNW_IA64_FR + 2: loc = c->loc[IA64_REG_F2]; break; - case UNW_IA64_FR + 3: loc = c->loc[IA64_REG_F3]; break; - case UNW_IA64_FR + 4: loc = c->loc[IA64_REG_F4]; break; - case UNW_IA64_FR + 5: loc = c->loc[IA64_REG_F5]; break; - - case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31: - loc = c->loc[IA64_REG_F16 + (reg - (UNW_IA64_FR + 16))]; - break; - - case UNW_IA64_FR + 6 ... UNW_IA64_FR + 15: - loc = ia64_scratch_loc (c, reg, NULL); - break; - - case UNW_IA64_FR + 32 ... UNW_IA64_FR + 127: - reg = rotate_fr (c, reg - UNW_IA64_FR) + UNW_IA64_FR; - loc = ia64_scratch_loc (c, reg, NULL); - break; - - default: - Debug (1, "bad register number %d\n", reg); - return -UNW_EBADREG; - } - - if (write) - return ia64_putfp (c, loc, *valp); - else - return ia64_getfp (c, loc, valp); -} diff --git a/contrib/libunwind/src/ia64/Gresume.c b/contrib/libunwind/src/ia64/Gresume.c deleted file mode 100644 index aa395b69a35..00000000000 --- a/contrib/libunwind/src/ia64/Gresume.c +++ /dev/null @@ -1,274 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" -#include "offsets.h" - -#ifndef UNW_REMOTE_ONLY - -static inline int -local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ -#if defined(__linux) - unw_word_t dirty_partition[2048]; /* AR.RSC.LOADRS is a 14-bit field */ - unw_word_t val, sol, sof, pri_unat, n, pfs, bspstore, dirty_rnat; - struct cursor *c = (struct cursor *) cursor; - struct - { - unw_word_t r1; - unw_word_t r4; - unw_word_t r5; - unw_word_t r6; - unw_word_t r7; - unw_word_t r15; - unw_word_t r16; - unw_word_t r17; - unw_word_t r18; - } - extra; - int ret, dirty_size; -# define GET_NAT(n) \ - do \ - { \ - ret = tdep_access_reg (c, UNW_IA64_NAT + (n), &val, 0); \ - if (ret < 0) \ - return ret; \ - if (val) \ - pri_unat |= (unw_word_t) 1 << n; \ - } \ - while (0) - - /* ensure c->pi is up-to-date: */ - if ((ret = ia64_make_proc_info (c)) < 0) - return ret; - - /* Copy contents of r4-r7 into "extra", so that their values end up - contiguous, so we can use a single (primary-) UNaT value. */ - if ((ret = ia64_get (c, c->loc[IA64_REG_R4], &extra.r4)) < 0 - || (ret = ia64_get (c, c->loc[IA64_REG_R5], &extra.r5)) < 0 - || (ret = ia64_get (c, c->loc[IA64_REG_R6], &extra.r6)) < 0 - || (ret = ia64_get (c, c->loc[IA64_REG_R7], &extra.r7)) < 0) - return ret; - - /* Form the primary UNaT value: */ - pri_unat = 0; - GET_NAT (4); GET_NAT(5); - GET_NAT (6); GET_NAT(7); - n = (((uintptr_t) &extra.r4) / 8 - 4) % 64; - pri_unat = (pri_unat << n) | (pri_unat >> (64 - n)); - - if (unlikely (c->sigcontext_addr)) - { - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; -# define PR_SCRATCH 0xffc0 /* p6-p15 are scratch */ -# define PR_PRESERVED (~(PR_SCRATCH | 1)) - - /* We're returning to a frame that was (either directly or - indirectly) interrupted by a signal. We have to restore - _both_ "preserved" and "scratch" registers. That doesn't - leave us any registers to work with, and the only way we can - achieve this is by doing a sigreturn(). - - Note: it might be tempting to think that we don't have to - restore the scratch registers when returning to a frame that - was indirectly interrupted by a signal. However, that is not - safe because that frame and its descendants could have been - using a special convention that stores "preserved" state in - scratch registers. For example, the Linux fsyscall - convention does this with r11 (to save ar.pfs) and b6 (to - save "rp"). */ - - sc->sc_gr[12] = c->psp; - c->psp = c->sigcontext_addr - c->sigcontext_off; - - sof = (c->cfm & 0x7f); - if ((dirty_size = rbs_cover_and_flush (c, sof, dirty_partition, - &dirty_rnat, &bspstore)) < 0) - return dirty_size; - - /* Clear the "in-syscall" flag, because in general we won't be - returning to the interruption-point and we need all registers - restored. */ - sc->sc_flags &= ~IA64_SC_FLAG_IN_SYSCALL; - sc->sc_ip = c->ip; - sc->sc_cfm = c->cfm & (((unw_word_t) 1 << 38) - 1); - sc->sc_pr = (c->pr & ~PR_SCRATCH) | (sc->sc_pr & ~PR_PRESERVED); - if ((ret = ia64_get (c, c->loc[IA64_REG_PFS], &sc->sc_ar_pfs)) < 0 - || (ret = ia64_get (c, c->loc[IA64_REG_FPSR], &sc->sc_ar_fpsr)) < 0 - || (ret = ia64_get (c, c->loc[IA64_REG_UNAT], &sc->sc_ar_unat)) < 0) - return ret; - - sc->sc_gr[1] = c->pi.gp; - if (c->eh_valid_mask & 0x1) sc->sc_gr[15] = c->eh_args[0]; - if (c->eh_valid_mask & 0x2) sc->sc_gr[16] = c->eh_args[1]; - if (c->eh_valid_mask & 0x4) sc->sc_gr[17] = c->eh_args[2]; - if (c->eh_valid_mask & 0x8) sc->sc_gr[18] = c->eh_args[3]; - Debug (9, "sc: r15=%lx,r16=%lx,r17=%lx,r18=%lx\n", - (long) sc->sc_gr[15], (long) sc->sc_gr[16], - (long) sc->sc_gr[17], (long) sc->sc_gr[18]); - } - else - { - /* Account for the fact that _Uia64_install_context() will - return via br.ret, which will decrement bsp by size-of-locals. */ - if ((ret = ia64_get (c, c->loc[IA64_REG_PFS], &pfs)) < 0) - return ret; - sol = (pfs >> 7) & 0x7f; - if ((dirty_size = rbs_cover_and_flush (c, sol, dirty_partition, - &dirty_rnat, &bspstore)) < 0) - return dirty_size; - - extra.r1 = c->pi.gp; - extra.r15 = c->eh_args[0]; - extra.r16 = c->eh_args[1]; - extra.r17 = c->eh_args[2]; - extra.r18 = c->eh_args[3]; - Debug (9, "extra: r15=%lx,r16=%lx,r17=%lx,r18=%lx\n", - (long) extra.r15, (long) extra.r16, - (long) extra.r17, (long) extra.r18); - } - Debug (8, "resuming at ip=%lx\n", (long) c->ip); - ia64_install_cursor (c, pri_unat, (unw_word_t *) &extra, - bspstore, dirty_size, dirty_partition + dirty_size/8, - dirty_rnat); -#elif defined(__hpux) - struct cursor *c = (struct cursor *) cursor; - - setcontext (c->as_arg); /* should not return */ -#endif - return -UNW_EINVAL; -} - -HIDDEN int -ia64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ - return local_resume (as, cursor, arg); -} - -#endif /* !UNW_REMOTE_ONLY */ - -#ifndef UNW_LOCAL_ONLY - -static inline int -remote_install_cursor (struct cursor *c) -{ - int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, - int write, void *); - int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, - int write, void *); - unw_fpreg_t fpval; - unw_word_t val; - int reg; - -#if defined(__linux) && !defined(UNW_REMOTE_ONLY) - if (c->as == unw_local_addr_space) - { - /* Take a short-cut: we directly resume out of the cursor and - all we need to do is make sure that all locations point to - memory, not registers. Furthermore, R4-R7 and NAT4-NAT7 are - taken care of by ia64_local_resume() so they don't need to be - handled here. */ -# define MEMIFY(preg, reg) \ - do { \ - if (IA64_IS_REG_LOC (c->loc[(preg)])) \ - c->loc[(preg)] = IA64_LOC_ADDR ((unw_word_t) \ - tdep_uc_addr(c->as_arg, (reg), \ - NULL), 0); \ - } while (0) - MEMIFY (IA64_REG_PR, UNW_IA64_PR); - MEMIFY (IA64_REG_PFS, UNW_IA64_AR_PFS); - MEMIFY (IA64_REG_RNAT, UNW_IA64_AR_RNAT); - MEMIFY (IA64_REG_UNAT, UNW_IA64_AR_UNAT); - MEMIFY (IA64_REG_LC, UNW_IA64_AR_LC); - MEMIFY (IA64_REG_FPSR, UNW_IA64_AR_FPSR); - MEMIFY (IA64_REG_IP, UNW_IA64_BR + 0); - MEMIFY (IA64_REG_B1, UNW_IA64_BR + 1); - MEMIFY (IA64_REG_B2, UNW_IA64_BR + 2); - MEMIFY (IA64_REG_B3, UNW_IA64_BR + 3); - MEMIFY (IA64_REG_B4, UNW_IA64_BR + 4); - MEMIFY (IA64_REG_B5, UNW_IA64_BR + 5); - MEMIFY (IA64_REG_F2, UNW_IA64_FR + 2); - MEMIFY (IA64_REG_F3, UNW_IA64_FR + 3); - MEMIFY (IA64_REG_F4, UNW_IA64_FR + 4); - MEMIFY (IA64_REG_F5, UNW_IA64_FR + 5); - MEMIFY (IA64_REG_F16, UNW_IA64_FR + 16); - MEMIFY (IA64_REG_F17, UNW_IA64_FR + 17); - MEMIFY (IA64_REG_F18, UNW_IA64_FR + 18); - MEMIFY (IA64_REG_F19, UNW_IA64_FR + 19); - MEMIFY (IA64_REG_F20, UNW_IA64_FR + 20); - MEMIFY (IA64_REG_F21, UNW_IA64_FR + 21); - MEMIFY (IA64_REG_F22, UNW_IA64_FR + 22); - MEMIFY (IA64_REG_F23, UNW_IA64_FR + 23); - MEMIFY (IA64_REG_F24, UNW_IA64_FR + 24); - MEMIFY (IA64_REG_F25, UNW_IA64_FR + 25); - MEMIFY (IA64_REG_F26, UNW_IA64_FR + 26); - MEMIFY (IA64_REG_F27, UNW_IA64_FR + 27); - MEMIFY (IA64_REG_F28, UNW_IA64_FR + 28); - MEMIFY (IA64_REG_F29, UNW_IA64_FR + 29); - MEMIFY (IA64_REG_F30, UNW_IA64_FR + 30); - MEMIFY (IA64_REG_F31, UNW_IA64_FR + 31); - } - else -#endif /* __linux && !UNW_REMOTE_ONLY */ - { - access_reg = c->as->acc.access_reg; - access_fpreg = c->as->acc.access_fpreg; - - Debug (8, "copying out cursor state\n"); - - for (reg = 0; reg <= UNW_REG_LAST; ++reg) - { - if (unw_is_fpreg (reg)) - { - if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) - (*access_fpreg) (c->as, reg, &fpval, 1, c->as_arg); - } - else - { - if (tdep_access_reg (c, reg, &val, 0) >= 0) - (*access_reg) (c->as, reg, &val, 1, c->as_arg); - } - } - } - return (*c->as->acc.resume) (c->as, (unw_cursor_t *) c, c->as_arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - -PROTECTED int -unw_resume (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - - Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->ip); - -#ifdef UNW_LOCAL_ONLY - return local_resume (c->as, cursor, c->as_arg); -#else - return remote_install_cursor (c); -#endif -} diff --git a/contrib/libunwind/src/ia64/Gscript.c b/contrib/libunwind/src/ia64/Gscript.c deleted file mode 100644 index 526aeaf299e..00000000000 --- a/contrib/libunwind/src/ia64/Gscript.c +++ /dev/null @@ -1,765 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "offsets.h" -#include "regs.h" -#include "unwind_i.h" - -enum ia64_script_insn_opcode - { - IA64_INSN_INC_PSP, /* psp += val */ - IA64_INSN_LOAD_PSP, /* psp = *psp_loc */ - IA64_INSN_ADD_PSP, /* s[dst] = (s.psp + val) */ - IA64_INSN_ADD_PSP_NAT, /* like above, but with NaT info */ - IA64_INSN_ADD_SP, /* s[dst] = (s.sp + val) */ - IA64_INSN_ADD_SP_NAT, /* like above, but with NaT info */ - IA64_INSN_MOVE, /* s[dst] = s[val] */ - IA64_INSN_MOVE_NAT, /* like above, but with NaT info */ - IA64_INSN_MOVE_NO_NAT, /* like above, but clear NaT info */ - IA64_INSN_MOVE_STACKED, /* s[dst] = rse_skip(*s.bsp_loc, val) */ - IA64_INSN_MOVE_STACKED_NAT, /* like above, but with NaT info */ - IA64_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */ - IA64_INSN_MOVE_SCRATCH_NAT, /* like above, but with NaT info */ - IA64_INSN_MOVE_SCRATCH_NO_NAT /* like above, but clear NaT info */ - }; - -#if defined(HAVE___THREAD) && HAVE___THREAD -static __thread struct ia64_script_cache ia64_per_thread_cache = - { -#ifdef HAVE_ATOMIC_OPS_H - .busy = AO_TS_INITIALIZER -#else - .lock = PTHREAD_MUTEX_INITIALIZER -#endif - }; -#endif - -static inline unw_hash_index_t CONST_ATTR -hash (unw_word_t ip) -{ - /* based on (sqrt(5)/2-1)*2^64 */ -# define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL) - - return (ip >> 4) * magic >> (64 - IA64_LOG_UNW_HASH_SIZE); -} - -static inline long -cache_match (struct ia64_script *script, unw_word_t ip, unw_word_t pr) -{ - if (ip == script->ip && ((pr ^ script->pr_val) & script->pr_mask) == 0) - return 1; - return 0; -} - -static inline void -flush_script_cache (struct ia64_script_cache *cache) -{ - int i; - - cache->lru_head = IA64_UNW_CACHE_SIZE - 1; - cache->lru_tail = 0; - - for (i = 0; i < IA64_UNW_CACHE_SIZE; ++i) - { - if (i > 0) - cache->buckets[i].lru_chain = (i - 1); - cache->buckets[i].coll_chain = -1; - cache->buckets[i].ip = 0; - } - for (i = 0; ihash[i] = -1; -} - -static inline struct ia64_script_cache * -get_script_cache (unw_addr_space_t as, intrmask_t *saved_maskp) -{ - struct ia64_script_cache *cache = &as->global_cache; - unw_caching_policy_t caching = as->caching_policy; - - if (caching == UNW_CACHE_NONE) - return NULL; - -#ifdef HAVE_ATOMIC_H - if (!spin_trylock_irqsave (&cache->busy, *saved_maskp)) - return NULL; -#else -# if defined(HAVE___THREAD) && HAVE___THREAD - if (as->caching_policy == UNW_CACHE_PER_THREAD) - cache = &ia64_per_thread_cache; -# endif -# ifdef HAVE_ATOMIC_OPS_H - if (AO_test_and_set (&cache->busy) == AO_TS_SET) - return NULL; -# else - if (likely (caching == UNW_CACHE_GLOBAL)) - { - Debug (16, "acquiring lock\n"); - lock_acquire (&cache->lock, *saved_maskp); - } -# endif -#endif - - if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation)) - { - flush_script_cache (cache); - cache->generation = as->cache_generation; - } - return cache; -} - -static inline void -put_script_cache (unw_addr_space_t as, struct ia64_script_cache *cache, - intrmask_t *saved_maskp) -{ - assert (as->caching_policy != UNW_CACHE_NONE); - - Debug (16, "unmasking signals/interrupts and releasing lock\n"); -#ifdef HAVE_ATOMIC_H - spin_unlock_irqrestore (&cache->busy, *saved_maskp); -#else -# ifdef HAVE_ATOMIC_OPS_H - AO_CLEAR (&cache->busy); -# else - if (likely (as->caching_policy == UNW_CACHE_GLOBAL)) - lock_release (&cache->lock, *saved_maskp); -# endif -#endif -} - -static struct ia64_script * -script_lookup (struct ia64_script_cache *cache, struct cursor *c) -{ - struct ia64_script *script = cache->buckets + c->hint; - unsigned short index; - unw_word_t ip, pr; - - ip = c->ip; - pr = c->pr; - - if (cache_match (script, ip, pr)) - return script; - - index = cache->hash[hash (ip)]; - if (index >= IA64_UNW_CACHE_SIZE) - return 0; - - script = cache->buckets + index; - while (1) - { - if (cache_match (script, ip, pr)) - { - /* update hint; no locking needed: single-word writes are atomic */ - c->hint = cache->buckets[c->prev_script].hint = - (script - cache->buckets); - return script; - } - if (script->coll_chain >= IA64_UNW_HASH_SIZE) - return 0; - script = cache->buckets + script->coll_chain; - } -} - -static inline void -script_init (struct ia64_script *script, unw_word_t ip) -{ - script->ip = ip; - script->hint = 0; - script->count = 0; - script->abi_marker = 0; -} - -static inline struct ia64_script * -script_new (struct ia64_script_cache *cache, unw_word_t ip) -{ - struct ia64_script *script, *prev, *tmp; - unw_hash_index_t index; - unsigned short head; - - head = cache->lru_head; - script = cache->buckets + head; - cache->lru_head = script->lru_chain; - - /* re-insert script at the tail of the LRU chain: */ - cache->buckets[cache->lru_tail].lru_chain = head; - cache->lru_tail = head; - - /* remove the old script from the hash table (if it's there): */ - if (script->ip) - { - index = hash (script->ip); - tmp = cache->buckets + cache->hash[index]; - prev = 0; - while (1) - { - if (tmp == script) - { - if (prev) - prev->coll_chain = tmp->coll_chain; - else - cache->hash[index] = tmp->coll_chain; - break; - } - else - prev = tmp; - if (tmp->coll_chain >= IA64_UNW_CACHE_SIZE) - /* old script wasn't in the hash-table */ - break; - tmp = cache->buckets + tmp->coll_chain; - } - } - - /* enter new script in the hash table */ - index = hash (ip); - script->coll_chain = cache->hash[index]; - cache->hash[index] = script - cache->buckets; - - script_init (script, ip); - return script; -} - -static inline void -script_finalize (struct ia64_script *script, struct cursor *c, - struct ia64_state_record *sr) -{ - script->pr_mask = sr->pr_mask; - script->pr_val = sr->pr_val; - script->pi = c->pi; -} - -static inline void -script_emit (struct ia64_script *script, struct ia64_script_insn insn) -{ - if (script->count >= IA64_MAX_SCRIPT_LEN) - { - Dprintf ("%s: script exceeds maximum size of %u instructions!\n", - __FUNCTION__, IA64_MAX_SCRIPT_LEN); - return; - } - script->insn[script->count++] = insn; -} - -static void -compile_reg (struct ia64_state_record *sr, int i, struct ia64_reg_info *r, - struct ia64_script *script) -{ - enum ia64_script_insn_opcode opc; - unsigned long val, rval; - struct ia64_script_insn insn; - long is_preserved_gr; - - if (r->where == IA64_WHERE_NONE || r->when >= sr->when_target) - return; - - opc = IA64_INSN_MOVE; - val = rval = r->val; - is_preserved_gr = (i >= IA64_REG_R4 && i <= IA64_REG_R7); - - if (r->where == IA64_WHERE_GR) - { - /* Handle most common case first... */ - if (rval >= 32) - { - /* register got spilled to a stacked register */ - if (is_preserved_gr) - opc = IA64_INSN_MOVE_STACKED_NAT; - else - opc = IA64_INSN_MOVE_STACKED; - val = rval; - } - else if (rval >= 4 && rval <= 7) - { - /* register got spilled to a preserved register */ - val = IA64_REG_R4 + (rval - 4); - if (is_preserved_gr) - opc = IA64_INSN_MOVE_NAT; - } - else - { - /* register got spilled to a scratch register */ - if (is_preserved_gr) - opc = IA64_INSN_MOVE_SCRATCH_NAT; - else - opc = IA64_INSN_MOVE_SCRATCH; - val = UNW_IA64_GR + rval; - } - } - else - { - switch (r->where) - { - case IA64_WHERE_FR: - /* Note: There is no need to handle NaT-bit info here - (indepent of is_preserved_gr), because for floating-point - NaTs are represented as NaTVal, so the NaT-info never - needs to be consulated. */ - if (rval >= 2 && rval <= 5) - val = IA64_REG_F2 + (rval - 2); - else if (rval >= 16 && rval <= 31) - val = IA64_REG_F16 + (rval - 16); - else - { - opc = IA64_INSN_MOVE_SCRATCH; - val = UNW_IA64_FR + rval; - } - break; - - case IA64_WHERE_BR: - if (rval >= 1 && rval <= 5) - { - val = IA64_REG_B1 + (rval - 1); - if (is_preserved_gr) - opc = IA64_INSN_MOVE_NO_NAT; - } - else - { - opc = IA64_INSN_MOVE_SCRATCH; - if (is_preserved_gr) - opc = IA64_INSN_MOVE_SCRATCH_NO_NAT; - val = UNW_IA64_BR + rval; - } - break; - - case IA64_WHERE_SPREL: - if (is_preserved_gr) - opc = IA64_INSN_ADD_SP_NAT; - else - { - opc = IA64_INSN_ADD_SP; - if (i >= IA64_REG_F2 && i <= IA64_REG_F31) - val |= IA64_LOC_TYPE_FP; - } - break; - - case IA64_WHERE_PSPREL: - if (is_preserved_gr) - opc = IA64_INSN_ADD_PSP_NAT; - else - { - opc = IA64_INSN_ADD_PSP; - if (i >= IA64_REG_F2 && i <= IA64_REG_F31) - val |= IA64_LOC_TYPE_FP; - } - break; - - default: - Dprintf ("%s: register %u has unexpected `where' value of %u\n", - __FUNCTION__, i, r->where); - break; - } - } - insn.opc = opc; - insn.dst = i; - insn.val = val; - script_emit (script, insn); - - if (i == IA64_REG_PSP) - { - /* c->psp must contain the _value_ of the previous sp, not it's - save-location. We get this by dereferencing the value we - just stored in loc[IA64_REG_PSP]: */ - insn.opc = IA64_INSN_LOAD_PSP; - script_emit (script, insn); - } -} - -/* Sort the registers which got saved in decreasing order of WHEN - value. This is needed to ensure that the save-locations are - updated in the proper order. For example, suppose r4 gets spilled - to memory and then r5 gets saved in r4. In this case, we need to - update the save location of r5 before the one of r4. */ - -static inline int -sort_regs (struct ia64_state_record *sr, int regorder[]) -{ - int r, i, j, max, max_reg, max_when, num_regs = 0; - - assert (IA64_REG_BSP == 3); - - for (r = IA64_REG_BSP; r < IA64_NUM_PREGS; ++r) - { - if (sr->curr.reg[r].where == IA64_WHERE_NONE - || sr->curr.reg[r].when >= sr->when_target) - continue; - - regorder[num_regs++] = r; - } - - /* Simple insertion-sort. Involves about N^2/2 comparisons and N - exchanges. N is often small (say, 2-5) so a fancier sorting - algorithm may not be worthwhile. */ - - for (i = max = 0; i < num_regs - 1; ++i) - { - max_reg = regorder[max]; - max_when = sr->curr.reg[max_reg].when; - - for (j = i + 1; j < num_regs; ++j) - if (sr->curr.reg[regorder[j]].when > max_when) - { - max = j; - max_reg = regorder[j]; - max_when = sr->curr.reg[max_reg].when; - } - if (i != max) - { - regorder[max] = regorder[i]; - regorder[i] = max_reg; - } - } - return num_regs; -} - -/* Build an unwind script that unwinds from state OLD_STATE to the - entrypoint of the function that called OLD_STATE. */ - -static inline int -build_script (struct cursor *c, struct ia64_script *script) -{ - int num_regs, i, ret, regorder[IA64_NUM_PREGS - 3]; - struct ia64_reg_info *pri_unat; - struct ia64_state_record sr; - struct ia64_script_insn insn; - - ret = ia64_create_state_record (c, &sr); - if (ret < 0) - return ret; - - /* First, compile the update for IA64_REG_PSP. This is important - because later save-locations may depend on it's correct (updated) - value. Fixed-size frames are handled specially and variable-size - frames get handled via the normal compile_reg(). */ - - if (sr.when_target > sr.curr.reg[IA64_REG_PSP].when - && (sr.curr.reg[IA64_REG_PSP].where == IA64_WHERE_NONE) - && sr.curr.reg[IA64_REG_PSP].val != 0) - { - /* new psp is psp plus frame size */ - insn.opc = IA64_INSN_INC_PSP; - insn.val = sr.curr.reg[IA64_REG_PSP].val; /* frame size */ - script_emit (script, insn); - } - else - compile_reg (&sr, IA64_REG_PSP, sr.curr.reg + IA64_REG_PSP, script); - - /* Second, compile the update for the primary UNaT, if any: */ - - if (sr.when_target >= sr.curr.reg[IA64_REG_PRI_UNAT_GR].when - || sr.when_target >= sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when) - { - if (sr.when_target < sr.curr.reg[IA64_REG_PRI_UNAT_GR].when) - /* (primary) NaT bits were saved to memory only */ - pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_MEM; - else if (sr.when_target < sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when) - /* (primary) NaT bits were saved to a register only */ - pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_GR; - else if (sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when > - sr.curr.reg[IA64_REG_PRI_UNAT_GR].when) - /* (primary) NaT bits were last saved to memory */ - pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_MEM; - else - /* (primary) NaT bits were last saved to a register */ - pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_GR; - - /* Note: we always store the final primary-UNaT location in UNAT_MEM. */ - compile_reg (&sr, IA64_REG_PRI_UNAT_MEM, pri_unat, script); - } - - /* Third, compile the other register in decreasing order of WHEN values. */ - - num_regs = sort_regs (&sr, regorder); - for (i = 0; i < num_regs; ++i) - compile_reg (&sr, regorder[i], sr.curr.reg + regorder[i], script); - - script->abi_marker = sr.abi_marker; - script_finalize (script, c, &sr); - - ia64_free_state_record (&sr); - return 0; -} - -static inline void -set_nat_info (struct cursor *c, unsigned long dst, - ia64_loc_t nat_loc, uint8_t bitnr) -{ - assert (dst >= IA64_REG_R4 && dst <= IA64_REG_R7); - - c->loc[dst - IA64_REG_R4 + IA64_REG_NAT4] = nat_loc; - c->nat_bitnr[dst - IA64_REG_R4] = bitnr; -} - -/* Apply the unwinding actions represented by OPS and update SR to - reflect the state that existed upon entry to the function that this - unwinder represents. */ - -static inline int -run_script (struct ia64_script *script, struct cursor *c) -{ - struct ia64_script_insn *ip, *limit, next_insn; - ia64_loc_t loc, nat_loc; - unsigned long opc, dst; - uint8_t nat_bitnr; - unw_word_t val; - int ret; - - c->pi = script->pi; - ip = script->insn; - limit = script->insn + script->count; - next_insn = *ip; - c->abi_marker = script->abi_marker; - - while (ip++ < limit) - { - opc = next_insn.opc; - dst = next_insn.dst; - val = next_insn.val; - next_insn = *ip; - - /* This is by far the most common operation: */ - if (likely (opc == IA64_INSN_MOVE_STACKED)) - { - if ((ret = ia64_get_stacked (c, val, &loc, NULL)) < 0) - return ret; - } - else - switch (opc) - { - case IA64_INSN_INC_PSP: - c->psp += val; - continue; - - case IA64_INSN_LOAD_PSP: - if ((ret = ia64_get (c, c->loc[IA64_REG_PSP], &c->psp)) < 0) - return ret; - continue; - - case IA64_INSN_ADD_PSP: - loc = IA64_LOC_ADDR (c->psp + val, (val & IA64_LOC_TYPE_FP)); - break; - - case IA64_INSN_ADD_SP: - loc = IA64_LOC_ADDR (c->sp + val, (val & IA64_LOC_TYPE_FP)); - break; - - case IA64_INSN_MOVE_NO_NAT: - set_nat_info (c, dst, IA64_NULL_LOC, 0); - case IA64_INSN_MOVE: - loc = c->loc[val]; - break; - - case IA64_INSN_MOVE_SCRATCH_NO_NAT: - set_nat_info (c, dst, IA64_NULL_LOC, 0); - case IA64_INSN_MOVE_SCRATCH: - loc = ia64_scratch_loc (c, val, NULL); - break; - - case IA64_INSN_ADD_PSP_NAT: - loc = IA64_LOC_ADDR (c->psp + val, 0); - assert (!IA64_IS_REG_LOC (loc)); - set_nat_info (c, dst, - c->loc[IA64_REG_PRI_UNAT_MEM], - ia64_unat_slot_num (IA64_GET_ADDR (loc))); - break; - - case IA64_INSN_ADD_SP_NAT: - loc = IA64_LOC_ADDR (c->sp + val, 0); - assert (!IA64_IS_REG_LOC (loc)); - set_nat_info (c, dst, - c->loc[IA64_REG_PRI_UNAT_MEM], - ia64_unat_slot_num (IA64_GET_ADDR (loc))); - break; - - case IA64_INSN_MOVE_NAT: - loc = c->loc[val]; - set_nat_info (c, dst, - c->loc[val - IA64_REG_R4 + IA64_REG_NAT4], - c->nat_bitnr[val - IA64_REG_R4]); - break; - - case IA64_INSN_MOVE_STACKED_NAT: - if ((ret = ia64_get_stacked (c, val, &loc, &nat_loc)) < 0) - return ret; - assert (!IA64_IS_REG_LOC (loc)); - set_nat_info (c, dst, nat_loc, rse_slot_num (IA64_GET_ADDR (loc))); - break; - - case IA64_INSN_MOVE_SCRATCH_NAT: - loc = ia64_scratch_loc (c, val, NULL); - nat_loc = ia64_scratch_loc (c, val + (UNW_IA64_NAT - UNW_IA64_GR), - &nat_bitnr); - set_nat_info (c, dst, nat_loc, nat_bitnr); - break; - } - c->loc[dst] = loc; - } - return 0; -} - -static int -uncached_find_save_locs (struct cursor *c) -{ - struct ia64_script script; - int ret = 0; - - if ((ret = ia64_fetch_proc_info (c, c->ip, 1)) < 0) - return ret; - - script_init (&script, c->ip); - if ((ret = build_script (c, &script)) < 0) - { - if (ret != -UNW_ESTOPUNWIND) - Dprintf ("%s: failed to build unwind script for ip %lx\n", - __FUNCTION__, (long) c->ip); - return ret; - } - return run_script (&script, c); -} - -HIDDEN int -ia64_find_save_locs (struct cursor *c) -{ - struct ia64_script_cache *cache = NULL; - struct ia64_script *script = NULL; - intrmask_t saved_mask; - int ret = 0; - - if (c->as->caching_policy == UNW_CACHE_NONE) - return uncached_find_save_locs (c); - - cache = get_script_cache (c->as, &saved_mask); - if (!cache) - { - Debug (1, "contention on script-cache; doing uncached lookup\n"); - return uncached_find_save_locs (c); - } - { - script = script_lookup (cache, c); - Debug (8, "ip %lx %s in script cache\n", (long) c->ip, - script ? "hit" : "missed"); - - if (!script || (script->count == 0 && !script->pi.unwind_info)) - { - if ((ret = ia64_fetch_proc_info (c, c->ip, 1)) < 0) - goto out; - } - - if (!script) - { - script = script_new (cache, c->ip); - if (!script) - { - Dprintf ("%s: failed to create unwind script\n", __FUNCTION__); - ret = -UNW_EUNSPEC; - goto out; - } - } - cache->buckets[c->prev_script].hint = script - cache->buckets; - - if (script->count == 0) - ret = build_script (c, script); - - assert (script->count > 0); - - c->hint = script->hint; - c->prev_script = script - cache->buckets; - - if (ret < 0) - { - if (ret != -UNW_ESTOPUNWIND) - Dprintf ("%s: failed to locate/build unwind script for ip %lx\n", - __FUNCTION__, (long) c->ip); - goto out; - } - - ret = run_script (script, c); - } - out: - put_script_cache (c->as, cache, &saved_mask); - return ret; -} - -HIDDEN void -ia64_validate_cache (unw_addr_space_t as, void *arg) -{ -#ifndef UNW_REMOTE_ONLY - if (as == unw_local_addr_space && ia64_local_validate_cache (as, arg) == 1) - return; -#endif - -#ifndef UNW_LOCAL_ONLY - /* local info is up-to-date, check dynamic info. */ - unwi_dyn_validate_cache (as, arg); -#endif -} - -HIDDEN int -ia64_cache_proc_info (struct cursor *c) -{ - struct ia64_script_cache *cache; - struct ia64_script *script; - intrmask_t saved_mask; - int ret = 0; - - cache = get_script_cache (c->as, &saved_mask); - if (!cache) - return ret; /* cache is busy */ - - /* Re-check to see if a cache entry has been added in the meantime: */ - script = script_lookup (cache, c); - if (script) - goto out; - - script = script_new (cache, c->ip); - if (!script) - { - Dprintf ("%s: failed to create unwind script\n", __FUNCTION__); - ret = -UNW_EUNSPEC; - goto out; - } - - script->pi = c->pi; - - out: - put_script_cache (c->as, cache, &saved_mask); - return ret; -} - -HIDDEN int -ia64_get_cached_proc_info (struct cursor *c) -{ - struct ia64_script_cache *cache; - struct ia64_script *script; - intrmask_t saved_mask; - - cache = get_script_cache (c->as, &saved_mask); - if (!cache) - return -UNW_ENOINFO; /* cache is busy */ - { - script = script_lookup (cache, c); - if (script) - c->pi = script->pi; - } - put_script_cache (c->as, cache, &saved_mask); - return script ? 0 : -UNW_ENOINFO; -} diff --git a/contrib/libunwind/src/ia64/Gstep.c b/contrib/libunwind/src/ia64/Gstep.c deleted file mode 100644 index 0191f642a4c..00000000000 --- a/contrib/libunwind/src/ia64/Gstep.c +++ /dev/null @@ -1,359 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "offsets.h" -#include "unwind_i.h" - -static inline int -linux_sigtramp (struct cursor *c, ia64_loc_t prev_cfm_loc, - unw_word_t *num_regsp) -{ -#if defined(UNW_LOCAL_ONLY) && !defined(__linux) - return -UNW_EINVAL; -#else - unw_word_t sc_addr; - int ret; - - if ((ret = ia64_get (c, IA64_LOC_ADDR (c->sp + 0x10 - + LINUX_SIGFRAME_ARG2_OFF, 0), - &sc_addr)) < 0) - return ret; - - c->sigcontext_addr = sc_addr; - - if (!IA64_IS_REG_LOC (c->loc[IA64_REG_IP]) - && IA64_GET_ADDR (c->loc[IA64_REG_IP]) == sc_addr + LINUX_SC_BR_OFF + 8) - { - /* Linux kernels before 2.4.19 and 2.5.10 had buggy - unwind info for sigtramp. Fix it up here. */ - c->loc[IA64_REG_IP] = IA64_LOC_ADDR (sc_addr + LINUX_SC_IP_OFF, 0); - c->cfm_loc = IA64_LOC_ADDR (sc_addr + LINUX_SC_CFM_OFF, 0); - } - - /* do what can't be described by unwind directives: */ - c->loc[IA64_REG_PFS] = IA64_LOC_ADDR (sc_addr + LINUX_SC_AR_PFS_OFF, 0); - c->ec_loc = prev_cfm_loc; - *num_regsp = c->cfm & 0x7f; /* size of frame */ - return 0; -#endif -} - -static inline int -linux_interrupt (struct cursor *c, ia64_loc_t prev_cfm_loc, - unw_word_t *num_regsp, int marker) -{ -#if defined(UNW_LOCAL_ONLY) && !(defined(__linux) && defined(__KERNEL__)) - return -UNW_EINVAL; -#else - unw_word_t sc_addr, num_regs; - ia64_loc_t pfs_loc; - - sc_addr = c->sigcontext_addr = c->sp + 0x10; - - if ((c->pr & (1UL << LINUX_PT_P_NONSYS)) != 0) - num_regs = c->cfm & 0x7f; - else - num_regs = 0; - - /* do what can't be described by unwind directives: */ - if (marker == ABI_MARKER_OLD_LINUX_INTERRUPT) - pfs_loc = IA64_LOC_ADDR (sc_addr + LINUX_OLD_PT_PFS_OFF, 0); - else - pfs_loc = IA64_LOC_ADDR (sc_addr + LINUX_PT_PFS_OFF, 0); - c->loc[IA64_REG_PFS] = pfs_loc; - c->ec_loc = prev_cfm_loc; - *num_regsp = num_regs; /* size of frame */ - return 0; -#endif -} - -static inline int -hpux_sigtramp (struct cursor *c, ia64_loc_t prev_cfm_loc, - unw_word_t *num_regsp) -{ -#if defined(UNW_LOCAL_ONLY) && !defined(__hpux) - return -UNW_EINVAL; -#else - unw_word_t sc_addr, bsp, bspstore; - ia64_loc_t sc_loc; - int ret, i; - - /* HP-UX passes the address of ucontext_t in r32: */ - if ((ret = ia64_get_stacked (c, 32, &sc_loc, NULL)) < 0) - return ret; - if ((ret = ia64_get (c, sc_loc, &sc_addr)) < 0) - return ret; - - c->sigcontext_addr = sc_addr; - - /* Now mark all (preserved) registers as coming from the - signal context: */ - c->cfm_loc = IA64_LOC_UC_REG (UNW_IA64_CFM, sc_addr); - c->loc[IA64_REG_PRI_UNAT_MEM] = IA64_NULL_LOC; - c->loc[IA64_REG_PSP] = IA64_LOC_UC_REG (UNW_IA64_GR + 12, sc_addr); - c->loc[IA64_REG_BSP] = IA64_LOC_UC_REG (UNW_IA64_AR_BSP, sc_addr); - c->loc[IA64_REG_BSPSTORE] = IA64_LOC_UC_REG (UNW_IA64_AR_BSPSTORE, sc_addr); - c->loc[IA64_REG_PFS] = IA64_LOC_UC_REG (UNW_IA64_AR_PFS, sc_addr); - c->loc[IA64_REG_RNAT] = IA64_LOC_UC_REG (UNW_IA64_AR_RNAT, sc_addr); - c->loc[IA64_REG_IP] = IA64_LOC_UC_REG (UNW_IA64_IP, sc_addr); - c->loc[IA64_REG_R4] = IA64_LOC_UC_REG (UNW_IA64_GR + 4, sc_addr); - c->loc[IA64_REG_R5] = IA64_LOC_UC_REG (UNW_IA64_GR + 5, sc_addr); - c->loc[IA64_REG_R6] = IA64_LOC_UC_REG (UNW_IA64_GR + 6, sc_addr); - c->loc[IA64_REG_R7] = IA64_LOC_UC_REG (UNW_IA64_GR + 7, sc_addr); - c->loc[IA64_REG_NAT4] = IA64_LOC_UC_REG (UNW_IA64_NAT + 4, sc_addr); - c->loc[IA64_REG_NAT5] = IA64_LOC_UC_REG (UNW_IA64_NAT + 5, sc_addr); - c->loc[IA64_REG_NAT6] = IA64_LOC_UC_REG (UNW_IA64_NAT + 6, sc_addr); - c->loc[IA64_REG_NAT7] = IA64_LOC_UC_REG (UNW_IA64_NAT + 7, sc_addr); - c->loc[IA64_REG_UNAT] = IA64_LOC_UC_REG (UNW_IA64_AR_UNAT, sc_addr); - c->loc[IA64_REG_PR] = IA64_LOC_UC_REG (UNW_IA64_PR, sc_addr); - c->loc[IA64_REG_LC] = IA64_LOC_UC_REG (UNW_IA64_AR_LC, sc_addr); - c->loc[IA64_REG_FPSR] = IA64_LOC_UC_REG (UNW_IA64_AR_FPSR, sc_addr); - c->loc[IA64_REG_B1] = IA64_LOC_UC_REG (UNW_IA64_BR + 1, sc_addr); - c->loc[IA64_REG_B2] = IA64_LOC_UC_REG (UNW_IA64_BR + 2, sc_addr); - c->loc[IA64_REG_B3] = IA64_LOC_UC_REG (UNW_IA64_BR + 3, sc_addr); - c->loc[IA64_REG_B4] = IA64_LOC_UC_REG (UNW_IA64_BR + 4, sc_addr); - c->loc[IA64_REG_B5] = IA64_LOC_UC_REG (UNW_IA64_BR + 5, sc_addr); - c->loc[IA64_REG_F2] = IA64_LOC_UC_REG (UNW_IA64_FR + 2, sc_addr); - c->loc[IA64_REG_F3] = IA64_LOC_UC_REG (UNW_IA64_FR + 3, sc_addr); - c->loc[IA64_REG_F4] = IA64_LOC_UC_REG (UNW_IA64_FR + 4, sc_addr); - c->loc[IA64_REG_F5] = IA64_LOC_UC_REG (UNW_IA64_FR + 5, sc_addr); - for (i = 0; i < 16; ++i) - c->loc[IA64_REG_F16 + i] = IA64_LOC_UC_REG (UNW_IA64_FR + 16 + i, sc_addr); - - c->pi.flags |= UNW_PI_FLAG_IA64_RBS_SWITCH; - - /* update the CFM cache: */ - if ((ret = ia64_get (c, c->cfm_loc, &c->cfm)) < 0) - return ret; - /* update the PSP cache: */ - if ((ret = ia64_get (c, c->loc[IA64_REG_PSP], &c->psp)) < 0) - return ret; - - if ((ret = ia64_get (c, c->loc[IA64_REG_BSP], &bsp)) < 0 - || (ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &bspstore)) < 0) - return ret; - if (bspstore < bsp) - /* Dirty partition got spilled into the ucontext_t structure - itself. We'll need to access it via uc_access(3). */ - rbs_switch (c, bsp, bspstore, IA64_LOC_UC_ADDR (bsp | 0x1f8, 0)); - - c->ec_loc = prev_cfm_loc; - - *num_regsp = 0; - return 0; -#endif -} - - -static inline int -check_rbs_switch (struct cursor *c) -{ - unw_word_t saved_bsp, saved_bspstore, loadrs, ndirty; - int ret = 0; - - saved_bsp = c->bsp; - if (c->pi.flags & UNW_PI_FLAG_IA64_RBS_SWITCH) - { - /* Got ourselves a frame that has saved ar.bspstore, ar.bsp, - and ar.rnat, so we're all set for rbs-switching: */ - if ((ret = ia64_get (c, c->loc[IA64_REG_BSP], &saved_bsp)) < 0 - || (ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &saved_bspstore))) - return ret; - } - else if ((c->abi_marker == ABI_MARKER_LINUX_SIGTRAMP - || c->abi_marker == ABI_MARKER_OLD_LINUX_SIGTRAMP) - && !IA64_IS_REG_LOC (c->loc[IA64_REG_BSP]) - && (IA64_GET_ADDR (c->loc[IA64_REG_BSP]) - == c->sigcontext_addr + LINUX_SC_AR_BSP_OFF)) - { - /* When Linux delivers a signal on an alternate stack, it - does things a bit differently from what the unwind - conventions allow us to describe: instead of saving - ar.rnat, ar.bsp, and ar.bspstore, it saves the former two - plus the "loadrs" value. Because of this, we need to - detect & record a potential rbs-area switch - manually... */ - - /* If ar.bsp has been saved already AND the current bsp is - not equal to the saved value, then we know for sure that - we're past the point where the backing store has been - switched (and before the point where it's restored). */ - if ((ret = ia64_get (c, IA64_LOC_ADDR (c->sigcontext_addr - + LINUX_SC_AR_BSP_OFF, 0), - &saved_bsp) < 0) - || (ret = ia64_get (c, IA64_LOC_ADDR (c->sigcontext_addr - + LINUX_SC_LOADRS_OFF, 0), - &loadrs) < 0)) - return ret; - loadrs >>= 16; - ndirty = rse_num_regs (c->bsp - loadrs, c->bsp); - saved_bspstore = rse_skip_regs (saved_bsp, -ndirty); - } - - if (saved_bsp == c->bsp) - return 0; - - return rbs_switch (c, saved_bsp, saved_bspstore, c->loc[IA64_REG_RNAT]); -} - -static inline int -update_frame_state (struct cursor *c) -{ - unw_word_t prev_ip, prev_sp, prev_bsp, ip, num_regs; - ia64_loc_t prev_cfm_loc; - int ret; - - prev_cfm_loc = c->cfm_loc; - prev_ip = c->ip; - prev_sp = c->sp; - prev_bsp = c->bsp; - - /* Update the IP cache (do this first: if we reach the end of the - frame-chain, the rest of the info may not be valid/useful - anymore. */ - ret = ia64_get (c, c->loc[IA64_REG_IP], &ip); - if (ret < 0) - return ret; - c->ip = ip; - - if ((ip & 0xc) != 0) - { - /* don't let obviously bad addresses pollute the cache */ - Debug (1, "rejecting bad ip=0x%lx\n", (long) c->ip); - return -UNW_EINVALIDIP; - } - - c->cfm_loc = c->loc[IA64_REG_PFS]; - /* update the CFM cache: */ - ret = ia64_get (c, c->cfm_loc, &c->cfm); - if (ret < 0) - return ret; - - /* Normally, AR.EC is stored in the CFM save-location. That - save-location contains the full function-state as defined by - AR.PFS. However, interruptions only save the frame-marker, not - any other info in CFM. Instead, AR.EC gets saved on the first - call by the interruption-handler. Thus, interruption-related - frames need to track the _previous_ CFM save-location since - that's were AR.EC is saved. We support this by setting ec_loc to - cfm_loc by default and giving frames marked with an ABI-marker - the chance to override this value with prev_cfm_loc. */ - c->ec_loc = c->cfm_loc; - - num_regs = 0; - if (unlikely (c->abi_marker)) - { - c->last_abi_marker = c->abi_marker; - switch (ia64_get_abi_marker (c)) - { - case ABI_MARKER_LINUX_SIGTRAMP: - case ABI_MARKER_OLD_LINUX_SIGTRAMP: - ia64_set_abi (c, ABI_LINUX); - if ((ret = linux_sigtramp (c, prev_cfm_loc, &num_regs)) < 0) - return ret; - break; - - case ABI_MARKER_OLD_LINUX_INTERRUPT: - case ABI_MARKER_LINUX_INTERRUPT: - ia64_set_abi (c, ABI_LINUX); - if ((ret = linux_interrupt (c, prev_cfm_loc, &num_regs, - c->abi_marker)) < 0) - return ret; - break; - - case ABI_MARKER_HP_UX_SIGTRAMP: - ia64_set_abi (c, ABI_HPUX); - if ((ret = hpux_sigtramp (c, prev_cfm_loc, &num_regs)) < 0) - return ret; - break; - - default: - Debug (1, "unknown ABI marker: ABI=%u, context=%u\n", - c->abi_marker >> 8, c->abi_marker & 0xff); - return -UNW_EINVAL; - } - Debug (12, "sigcontext_addr=%lx (ret=%d)\n", - (unsigned long) c->sigcontext_addr, ret); - - c->sigcontext_off = c->sigcontext_addr - c->sp; - - /* update the IP cache: */ - if ((ret = ia64_get (c, c->loc[IA64_REG_IP], &ip)) < 0) - return ret; - c->ip = ip; - if (ip == 0) - /* end of frame-chain reached */ - return 0; - } - else - num_regs = (c->cfm >> 7) & 0x7f; /* size of locals */ - - if (!IA64_IS_NULL_LOC (c->loc[IA64_REG_BSP])) - { - ret = check_rbs_switch (c); - if (ret < 0) - return ret; - } - - c->bsp = rse_skip_regs (c->bsp, -num_regs); - - c->sp = c->psp; - c->abi_marker = 0; - - if (c->ip == prev_ip && c->sp == prev_sp && c->bsp == prev_bsp) - { - Dprintf ("%s: ip, sp, and bsp unchanged; stopping here (ip=0x%lx)\n", - __FUNCTION__, (long) ip); - return -UNW_EBADFRAME; - } - - /* as we unwind, the saved ar.unat becomes the primary unat: */ - c->loc[IA64_REG_PRI_UNAT_MEM] = c->loc[IA64_REG_UNAT]; - - /* restore the predicates: */ - ret = ia64_get (c, c->loc[IA64_REG_PR], &c->pr); - if (ret < 0) - return ret; - - c->pi_valid = 0; - return 0; -} - - -PROTECTED int -unw_step (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->ip); - - if ((ret = ia64_find_save_locs (c)) >= 0 - && (ret = update_frame_state (c)) >= 0) - ret = (c->ip == 0) ? 0 : 1; - - Debug (2, "returning %d (ip=0x%016lx)\n", ret, (unsigned long) c->ip); - return ret; -} diff --git a/contrib/libunwind/src/ia64/Gtables.c b/contrib/libunwind/src/ia64/Gtables.c deleted file mode 100644 index 6959cae98b0..00000000000 --- a/contrib/libunwind/src/ia64/Gtables.c +++ /dev/null @@ -1,731 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2001-2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include -#include - -#include "unwind_i.h" - -#ifdef HAVE_IA64INTRIN_H -# include -#endif - -extern unw_addr_space_t _ULia64_local_addr_space; - -struct ia64_table_entry - { - uint64_t start_offset; - uint64_t end_offset; - uint64_t info_offset; - }; - -#ifdef UNW_LOCAL_ONLY - -static inline int -is_local_addr_space (unw_addr_space_t as) -{ - return 1; -} - -static inline int -read_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, void *arg) -{ - *valp = *(unw_word_t *) addr; - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ - -static inline int -is_local_addr_space (unw_addr_space_t as) -{ - return as == unw_local_addr_space; -} - -static inline int -read_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, void *arg) -{ - unw_accessors_t *a = unw_get_accessors (as); - - return (*a->access_mem) (as, addr, valp, 0, arg); -} - -/* Helper macro for reading an ia64_table_entry from remote memory. */ -#define remote_read(addr, member) \ - (*a->access_mem) (as, (addr) + offsetof (struct ia64_table_entry, \ - member), &member, 0, arg) - -/* Lookup an unwind-table entry in remote memory. Returns 1 if an - entry is found, 0 if no entry is found, negative if an error - occurred reading remote memory. */ -static int -remote_lookup (unw_addr_space_t as, - unw_word_t table, size_t table_size, unw_word_t rel_ip, - struct ia64_table_entry *e, void *arg) -{ - unw_word_t e_addr = 0, start_offset, end_offset, info_offset; - unw_accessors_t *a = unw_get_accessors (as); - unsigned long lo, hi, mid; - int ret; - - /* do a binary search for right entry: */ - for (lo = 0, hi = table_size / sizeof (struct ia64_table_entry); lo < hi;) - { - mid = (lo + hi) / 2; - e_addr = table + mid * sizeof (struct ia64_table_entry); - if ((ret = remote_read (e_addr, start_offset)) < 0) - return ret; - - if (rel_ip < start_offset) - hi = mid; - else - { - if ((ret = remote_read (e_addr, end_offset)) < 0) - return ret; - - if (rel_ip >= end_offset) - lo = mid + 1; - else - break; - } - } - if (rel_ip < start_offset || rel_ip >= end_offset) - return 0; - e->start_offset = start_offset; - e->end_offset = end_offset; - - if ((ret = remote_read (e_addr, info_offset)) < 0) - return ret; - e->info_offset = info_offset; - return 1; -} - -HIDDEN void -tdep_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg) -{ - if (!pi->unwind_info) - return; - - if (is_local_addr_space (as)) - { - free (pi->unwind_info); - pi->unwind_info = NULL; - } -} - -PROTECTED unw_word_t -_Uia64_find_dyn_list (unw_addr_space_t as, unw_dyn_info_t *di, void *arg) -{ - unw_word_t hdr_addr, info_addr, hdr, directives, pers, cookie, off; - unw_word_t start_offset, end_offset, info_offset, segbase; - struct ia64_table_entry *e; - size_t table_size; - unw_word_t gp = di->gp; - int ret; - - switch (di->format) - { - case UNW_INFO_FORMAT_DYNAMIC: - default: - return 0; - - case UNW_INFO_FORMAT_TABLE: - e = (struct ia64_table_entry *) di->u.ti.table_data; - table_size = di->u.ti.table_len * sizeof (di->u.ti.table_data[0]); - segbase = di->u.ti.segbase; - if (table_size < sizeof (struct ia64_table_entry)) - return 0; - start_offset = e[0].start_offset; - end_offset = e[0].end_offset; - info_offset = e[0].info_offset; - break; - - case UNW_INFO_FORMAT_REMOTE_TABLE: - { - unw_accessors_t *a = unw_get_accessors (as); - unw_word_t e_addr = di->u.rti.table_data; - - table_size = di->u.rti.table_len * sizeof (unw_word_t); - segbase = di->u.rti.segbase; - if (table_size < sizeof (struct ia64_table_entry)) - return 0; - - if ( (ret = remote_read (e_addr, start_offset) < 0) - || (ret = remote_read (e_addr, end_offset) < 0) - || (ret = remote_read (e_addr, info_offset) < 0)) - return ret; - } - break; - } - - if (start_offset != end_offset) - /* dyn-list entry cover a zero-length "procedure" and should be - first entry (note: technically a binary could contain code - below the segment base, but this doesn't happen for normal - binaries and certainly doesn't happen when libunwind is a - separate shared object. For weird cases, the application may - have to provide its own (slower) version of this routine. */ - return 0; - - hdr_addr = info_offset + segbase; - info_addr = hdr_addr + 8; - - /* read the header word: */ - if ((ret = read_mem (as, hdr_addr, &hdr, arg)) < 0) - return ret; - - if (IA64_UNW_VER (hdr) != 1 - || IA64_UNW_FLAG_EHANDLER (hdr) || IA64_UNW_FLAG_UHANDLER (hdr)) - /* dyn-list entry must be version 1 and doesn't have ehandler - or uhandler */ - return 0; - - if (IA64_UNW_LENGTH (hdr) != 1) - /* dyn-list entry must consist of a single word of NOP directives */ - return 0; - - if ( ((ret = read_mem (as, info_addr, &directives, arg)) < 0) - || ((ret = read_mem (as, info_addr + 0x08, &pers, arg)) < 0) - || ((ret = read_mem (as, info_addr + 0x10, &cookie, arg)) < 0) - || ((ret = read_mem (as, info_addr + 0x18, &off, arg)) < 0)) - return 0; - - if (directives != 0 || pers != 0 - || (!as->big_endian && cookie != 0x7473696c2d6e7964ULL) - || ( as->big_endian && cookie != 0x64796e2d6c697374ULL)) - return 0; - - /* OK, we ran the gauntlet and found it: */ - return off + gp; -} - -#endif /* !UNW_LOCAL_ONLY */ - -static inline const struct ia64_table_entry * -lookup (struct ia64_table_entry *table, size_t table_size, unw_word_t rel_ip) -{ - const struct ia64_table_entry *e = 0; - unsigned long lo, hi, mid; - - /* do a binary search for right entry: */ - for (lo = 0, hi = table_size / sizeof (struct ia64_table_entry); lo < hi;) - { - mid = (lo + hi) / 2; - e = table + mid; - if (rel_ip < e->start_offset) - hi = mid; - else if (rel_ip >= e->end_offset) - lo = mid + 1; - else - break; - } - if (rel_ip < e->start_offset || rel_ip >= e->end_offset) - return NULL; - return e; -} - -PROTECTED int -unw_search_ia64_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - unw_word_t addr, hdr_addr, info_addr, info_end_addr, hdr, *wp; - const struct ia64_table_entry *e = NULL; - unw_word_t handler_offset, segbase = 0; - int ret, is_local; -#ifndef UNW_LOCAL_ONLY - struct ia64_table_entry ent; -#endif - - assert ((di->format == UNW_INFO_FORMAT_TABLE - || di->format == UNW_INFO_FORMAT_REMOTE_TABLE) - && (ip >= di->start_ip && ip < di->end_ip)); - - pi->flags = 0; - pi->unwind_info = 0; - pi->handler = 0; - - if (likely (di->format == UNW_INFO_FORMAT_TABLE)) - { - segbase = di->u.ti.segbase; - e = lookup ((struct ia64_table_entry *) di->u.ti.table_data, - di->u.ti.table_len * sizeof (unw_word_t), - ip - segbase); - } -#ifndef UNW_LOCAL_ONLY - else - { - segbase = di->u.rti.segbase; - if ((ret = remote_lookup (as, di->u.rti.table_data, - di->u.rti.table_len * sizeof (unw_word_t), - ip - segbase, &ent, arg)) < 0) - return ret; - if (ret) - e = &ent; - } -#endif - if (!e) - { - /* IP is inside this table's range, but there is no explicit - unwind info => use default conventions (i.e., this is NOT an - error). */ - memset (pi, 0, sizeof (*pi)); - pi->start_ip = 0; - pi->end_ip = 0; - pi->gp = di->gp; - pi->lsda = 0; - return 0; - } - - pi->start_ip = e->start_offset + segbase; - pi->end_ip = e->end_offset + segbase; - - hdr_addr = e->info_offset + segbase; - info_addr = hdr_addr + 8; - - /* Read the header word. Note: the actual unwind-info is always - assumed to reside in memory, independent of whether di->format is - UNW_INFO_FORMAT_TABLE or UNW_INFO_FORMAT_REMOTE_TABLE. */ - - if ((ret = read_mem (as, hdr_addr, &hdr, arg)) < 0) - return ret; - - if (IA64_UNW_VER (hdr) != 1) - { - Debug (1, "Unknown header version %ld (hdr word=0x%lx @ 0x%lx)\n", - IA64_UNW_VER (hdr), (unsigned long) hdr, - (unsigned long) hdr_addr); - return -UNW_EBADVERSION; - } - - info_end_addr = info_addr + 8 * IA64_UNW_LENGTH (hdr); - - is_local = is_local_addr_space (as); - - /* If we must have the unwind-info, return it. Also, if we are in - the local address-space, return the unwind-info because it's so - cheap to do so and it may come in handy later on. */ - if (need_unwind_info || is_local) - { - pi->unwind_info_size = 8 * IA64_UNW_LENGTH (hdr); - - if (is_local) - pi->unwind_info = (void *) (uintptr_t) info_addr; - else - { - /* Internalize unwind info. Note: since we're doing this - only for non-local address spaces, there is no - signal-safety issue and it is OK to use malloc()/free(). */ - pi->unwind_info = malloc (8 * IA64_UNW_LENGTH (hdr)); - if (!pi->unwind_info) - return -UNW_ENOMEM; - - wp = (unw_word_t *) pi->unwind_info; - for (addr = info_addr; addr < info_end_addr; addr += 8, ++wp) - { - if ((ret = read_mem (as, addr, wp, arg)) < 0) - { - free (pi->unwind_info); - return ret; - } - } - } - } - - if (IA64_UNW_FLAG_EHANDLER (hdr) || IA64_UNW_FLAG_UHANDLER (hdr)) - { - /* read the personality routine address (address is gp-relative): */ - if ((ret = read_mem (as, info_end_addr, &handler_offset, arg)) < 0) - return ret; - Debug (4, "handler ptr @ offset=%lx, gp=%lx\n", handler_offset, di->gp); - if ((read_mem (as, handler_offset + di->gp, &pi->handler, arg)) < 0) - return ret; - } - pi->lsda = info_end_addr + 8; - pi->gp = di->gp; - pi->format = di->format; - return 0; -} - -#ifndef UNW_REMOTE_ONLY - -# if defined(HAVE_DL_ITERATE_PHDR) -# include -# include - -# if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) \ - || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && !defined(DT_CONFIG)) -# error You need GLIBC 2.2.4 or later on IA-64 Linux -# endif - -# if defined(HAVE_GETUNWIND) - extern unsigned long getunwind (void *buf, size_t len); -# else /* HAVE_GETUNWIND */ -# include -# include -# ifndef __NR_getunwind -# define __NR_getunwind 1215 -# endif - -static unsigned long -getunwind (void *buf, size_t len) -{ - return syscall (SYS_getunwind, buf, len); -} - -# endif /* HAVE_GETUNWIND */ - -static unw_dyn_info_t kernel_table; - -static int -get_kernel_table (unw_dyn_info_t *di) -{ - struct ia64_table_entry *ktab, *etab; - size_t size; - - Debug (16, "getting kernel table"); - - size = getunwind (NULL, 0); - ktab = sos_alloc (size); - if (!ktab) - { - Dprintf (__FILE__".%s: failed to allocate %zu bytes", - __FUNCTION__, size); - return -UNW_ENOMEM; - } - getunwind (ktab, size); - - /* Determine length of kernel's unwind table & relocate its entries. */ - for (etab = ktab; etab->start_offset; ++etab) - etab->info_offset += (uint64_t) ktab; - - di->format = UNW_INFO_FORMAT_TABLE; - di->gp = 0; - di->start_ip = ktab[0].start_offset; - di->end_ip = etab[-1].end_offset; - di->u.ti.name_ptr = (unw_word_t) ""; - di->u.ti.segbase = 0; - di->u.ti.table_len = ((char *) etab - (char *) ktab) / sizeof (unw_word_t); - di->u.ti.table_data = (unw_word_t *) ktab; - - Debug (16, "found table `%s': [%lx-%lx) segbase=%lx len=%lu\n", - (char *) di->u.ti.name_ptr, di->start_ip, di->end_ip, - di->u.ti.segbase, di->u.ti.table_len); - return 0; -} - -# ifndef UNW_LOCAL_ONLY - -/* This is exported for the benefit of libunwind-ptrace.a. */ -PROTECTED int -_Uia64_get_kernel_table (unw_dyn_info_t *di) -{ - int ret; - - if (!kernel_table.u.ti.table_data) - if ((ret = get_kernel_table (&kernel_table)) < 0) - return ret; - - memcpy (di, &kernel_table, sizeof (*di)); - return 0; -} - -# endif /* !UNW_LOCAL_ONLY */ - -static inline unsigned long -current_gp (void) -{ -# if defined(__GNUC__) && !defined(__INTEL_COMPILER) - register unsigned long gp __asm__("gp"); - return gp; -# elif HAVE_IA64INTRIN_H - return __getReg (_IA64_REG_GP); -# else -# error Implement me. -# endif -} - -static int -callback (struct dl_phdr_info *info, size_t size, void *ptr) -{ - unw_dyn_info_t *di = ptr; - const Elf64_Phdr *phdr, *p_unwind, *p_dynamic, *p_text; - long n; - Elf64_Addr load_base, segbase = 0; - - /* Make sure struct dl_phdr_info is at least as big as we need. */ - if (size < offsetof (struct dl_phdr_info, dlpi_phnum) - + sizeof (info->dlpi_phnum)) - return -1; - - Debug (16, "checking `%s' (load_base=%lx)\n", - info->dlpi_name, info->dlpi_addr); - - phdr = info->dlpi_phdr; - load_base = info->dlpi_addr; - p_text = NULL; - p_unwind = NULL; - p_dynamic = NULL; - - /* See if PC falls into one of the loaded segments. Find the unwind - segment at the same time. */ - for (n = info->dlpi_phnum; --n >= 0; phdr++) - { - if (phdr->p_type == PT_LOAD) - { - Elf64_Addr vaddr = phdr->p_vaddr + load_base; - if (di->u.ti.segbase >= vaddr - && di->u.ti.segbase < vaddr + phdr->p_memsz) - p_text = phdr; - } - else if (phdr->p_type == PT_IA_64_UNWIND) - p_unwind = phdr; - else if (phdr->p_type == PT_DYNAMIC) - p_dynamic = phdr; - } - if (!p_text || !p_unwind) - return 0; - - if (likely (p_unwind->p_vaddr >= p_text->p_vaddr - && p_unwind->p_vaddr < p_text->p_vaddr + p_text->p_memsz)) - /* normal case: unwind table is inside text segment */ - segbase = p_text->p_vaddr + load_base; - else - { - /* Special case: unwind table is in some other segment; this - happens for the Linux kernel's gate DSO, for example. */ - phdr = info->dlpi_phdr; - for (n = info->dlpi_phnum; --n >= 0; phdr++) - { - if (phdr->p_type == PT_LOAD && p_unwind->p_vaddr >= phdr->p_vaddr - && p_unwind->p_vaddr < phdr->p_vaddr + phdr->p_memsz) - { - segbase = phdr->p_vaddr + load_base; - break; - } - } - } - - if (p_dynamic) - { - /* For dynamicly linked executables and shared libraries, - DT_PLTGOT is the gp value for that object. */ - Elf64_Dyn *dyn = (Elf64_Dyn *)(p_dynamic->p_vaddr + load_base); - for (; dyn->d_tag != DT_NULL; ++dyn) - if (dyn->d_tag == DT_PLTGOT) - { - /* On IA-64, _DYNAMIC is writable and GLIBC has relocated it. */ - di->gp = dyn->d_un.d_ptr; - break; - } - } - else - /* Otherwise this is a static executable with no _DYNAMIC. - The gp is constant program-wide. */ - di->gp = current_gp(); - di->format = UNW_INFO_FORMAT_TABLE; - di->start_ip = p_text->p_vaddr + load_base; - di->end_ip = p_text->p_vaddr + load_base + p_text->p_memsz; - di->u.ti.name_ptr = (unw_word_t) info->dlpi_name; - di->u.ti.table_data = (void *) (p_unwind->p_vaddr + load_base); - di->u.ti.table_len = p_unwind->p_memsz / sizeof (unw_word_t); - di->u.ti.segbase = segbase; - - Debug (16, "found table `%s': segbase=%lx, len=%lu, gp=%lx, " - "table_data=%p\n", (char *) di->u.ti.name_ptr, di->u.ti.segbase, - di->u.ti.table_len, di->gp, di->u.ti.table_data); - return 1; -} - -# ifdef HAVE_DL_PHDR_REMOVALS_COUNTER - -static inline int -validate_cache (unw_addr_space_t as) -{ - /* Note: we don't need to serialize here with respect to - dl_iterate_phdr() because if somebody were to remove an object - that is required to complete the unwind on whose behalf we're - validating the cache here, we'd be hosed anyhow. What we're - guarding against here is the case where library FOO gets mapped, - unwind info for FOO gets cached, FOO gets unmapped, BAR gets - mapped in the place where FOO was and then we unwind across a - function in FOO. Since no thread can execute in BAR before FOO - has been removed, we are guaranteed that - dl_phdr_removals_counter() would have been incremented before we - get here. */ - unsigned long long removals = dl_phdr_removals_counter (); - - if (removals == as->shared_object_removals) - return 1; - - as->shared_object_removals = removals; - unw_flush_cache (as, 0, 0); - return -1; -} - -# else /* !HAVE_DL_PHDR_REMOVALS_COUNTER */ - -/* Check whether any phdrs have been removed since we last flushed the - cache. If so we flush the cache and return -1, if not, we do - nothing and return 1. */ - -static int -check_callback (struct dl_phdr_info *info, size_t size, void *ptr) -{ -# ifdef HAVE_STRUCT_DL_PHDR_INFO_DLPI_SUBS - unw_addr_space_t as = ptr; - - if (size < - offsetof (struct dl_phdr_info, dlpi_subs) + sizeof (info->dlpi_subs)) - /* It would be safer to flush the cache here, but that would - disable caching for older libc's which would be incompatible - with the behavior of older versions of libunwind so we return 1 - instead and hope nobody runs into stale cache info... */ - return 1; - - if (info->dlpi_subs == as->shared_object_removals) - return 1; - - as->shared_object_removals = info->dlpi_subs; - unw_flush_cache (as, 0, 0); - return -1; /* indicate that there were removals */ -# else - return 1; -# endif -} - -static inline int -validate_cache (unw_addr_space_t as) -{ - intrmask_t saved_mask; - int ret; - - SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); - ret = dl_iterate_phdr (check_callback, as); - SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); - return ret; -} - -# endif /* HAVE_DL_PHDR_REMOVALS_COUNTER */ - -# elif defined(HAVE_DLMODINFO) - /* Support for HP-UX-style dlmodinfo() */ -# include - -static inline int -validate_cache (unw_addr_space_t as) -{ - return 1; -} - -# endif /* !HAVE_DLMODINFO */ - -HIDDEN int -tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, int need_unwind_info, void *arg) -{ -# if defined(HAVE_DL_ITERATE_PHDR) - unw_dyn_info_t di, *dip = &di; - intrmask_t saved_mask; - int ret; - - di.u.ti.segbase = ip; /* this is cheap... */ - - SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); - ret = dl_iterate_phdr (callback, &di); - SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); - - if (ret <= 0) - { - if (!kernel_table.u.ti.table_data) - { - if ((ret = get_kernel_table (&kernel_table)) < 0) - return ret; - } - if (ip < kernel_table.start_ip || ip >= kernel_table.end_ip) - return -UNW_ENOINFO; - dip = &kernel_table; - } -# elif defined(HAVE_DLMODINFO) -# define UNWIND_TBL_32BIT 0x8000000000000000 - struct load_module_desc lmd; - unw_dyn_info_t di, *dip = &di; - struct unwind_header - { - uint64_t header_version; - uint64_t start_offset; - uint64_t end_offset; - } - *uhdr; - - if (!dlmodinfo (ip, &lmd, sizeof (lmd), NULL, 0, 0)) - return -UNW_ENOINFO; - - di.format = UNW_INFO_FORMAT_TABLE; - di.start_ip = lmd.text_base; - di.end_ip = lmd.text_base + lmd.text_size; - di.gp = lmd.linkage_ptr; - di.u.ti.name_ptr = 0; /* no obvious table-name available */ - di.u.ti.segbase = lmd.text_base; - - uhdr = (struct unwind_header *) lmd.unwind_base; - - if ((uhdr->header_version & ~UNWIND_TBL_32BIT) != 1 - && (uhdr->header_version & ~UNWIND_TBL_32BIT) != 2) - { - Debug (1, "encountered unknown unwind header version %ld\n", - (long) (uhdr->header_version & ~UNWIND_TBL_32BIT)); - return -UNW_EBADVERSION; - } - if (uhdr->header_version & UNWIND_TBL_32BIT) - { - Debug (1, "32-bit unwind tables are not supported yet\n"); - return -UNW_EINVAL; - } - - di.u.ti.table_data = (unw_word_t *) (di.u.ti.segbase + uhdr->start_offset); - di.u.ti.table_len = ((uhdr->end_offset - uhdr->start_offset) - / sizeof (unw_word_t)); - - Debug (16, "found table `%s': segbase=%lx, len=%lu, gp=%lx, " - "table_data=%p\n", (char *) di.u.ti.name_ptr, di.u.ti.segbase, - di.u.ti.table_len, di.gp, di.u.ti.table_data); -# endif - - /* now search the table: */ - return tdep_search_unwind_table (as, ip, dip, pi, need_unwind_info, arg); -} - -/* Returns 1 if the cache is up-to-date or -1 if the cache contained - stale data and had to be flushed. */ - -HIDDEN int -ia64_local_validate_cache (unw_addr_space_t as, void *arg) -{ - return validate_cache (as); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/ia64/Lapply_reg_state.c b/contrib/libunwind/src/ia64/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/ia64/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lcreate_addr_space.c b/contrib/libunwind/src/ia64/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901..00000000000 --- a/contrib/libunwind/src/ia64/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lfind_unwind_table.c b/contrib/libunwind/src/ia64/Lfind_unwind_table.c deleted file mode 100644 index 68e269f1d7f..00000000000 --- a/contrib/libunwind/src/ia64/Lfind_unwind_table.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gfind_unwind_table.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lget_proc_info.c b/contrib/libunwind/src/ia64/Lget_proc_info.c deleted file mode 100644 index 69028b019fc..00000000000 --- a/contrib/libunwind/src/ia64/Lget_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lget_save_loc.c b/contrib/libunwind/src/ia64/Lget_save_loc.c deleted file mode 100644 index 9ea048a9076..00000000000 --- a/contrib/libunwind/src/ia64/Lget_save_loc.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_save_loc.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lglobal.c b/contrib/libunwind/src/ia64/Lglobal.c deleted file mode 100644 index 6d7b489e14b..00000000000 --- a/contrib/libunwind/src/ia64/Lglobal.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/contrib/libunwind/src/ia64/Linit.c b/contrib/libunwind/src/ia64/Linit.c deleted file mode 100644 index e9abfdd46a3..00000000000 --- a/contrib/libunwind/src/ia64/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/contrib/libunwind/src/ia64/Linit_local.c b/contrib/libunwind/src/ia64/Linit_local.c deleted file mode 100644 index 68a1687e854..00000000000 --- a/contrib/libunwind/src/ia64/Linit_local.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_local.c" -#endif diff --git a/contrib/libunwind/src/ia64/Linit_remote.c b/contrib/libunwind/src/ia64/Linit_remote.c deleted file mode 100644 index 58cb04ab7cd..00000000000 --- a/contrib/libunwind/src/ia64/Linit_remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_remote.c" -#endif diff --git a/contrib/libunwind/src/ia64/Linstall_cursor.S b/contrib/libunwind/src/ia64/Linstall_cursor.S deleted file mode 100644 index 8c723397252..00000000000 --- a/contrib/libunwind/src/ia64/Linstall_cursor.S +++ /dev/null @@ -1,6 +0,0 @@ -#define UNW_LOCAL_ONLY -#include "Ginstall_cursor.S" -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ia64/Lis_signal_frame.c b/contrib/libunwind/src/ia64/Lis_signal_frame.c deleted file mode 100644 index b9a7c4f51ad..00000000000 --- a/contrib/libunwind/src/ia64/Lis_signal_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gis_signal_frame.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lparser.c b/contrib/libunwind/src/ia64/Lparser.c deleted file mode 100644 index f23aaf48e9c..00000000000 --- a/contrib/libunwind/src/ia64/Lparser.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gparser.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lrbs.c b/contrib/libunwind/src/ia64/Lrbs.c deleted file mode 100644 index a91b5f2979a..00000000000 --- a/contrib/libunwind/src/ia64/Lrbs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Grbs.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lreg_states_iterate.c b/contrib/libunwind/src/ia64/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/ia64/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lregs.c b/contrib/libunwind/src/ia64/Lregs.c deleted file mode 100644 index 2c9c75cd7d9..00000000000 --- a/contrib/libunwind/src/ia64/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lresume.c b/contrib/libunwind/src/ia64/Lresume.c deleted file mode 100644 index 41a8cf003de..00000000000 --- a/contrib/libunwind/src/ia64/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lscript.c b/contrib/libunwind/src/ia64/Lscript.c deleted file mode 100644 index 57b926bf801..00000000000 --- a/contrib/libunwind/src/ia64/Lscript.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gscript.c" -#endif diff --git a/contrib/libunwind/src/ia64/Lstep.c b/contrib/libunwind/src/ia64/Lstep.c deleted file mode 100644 index c1ac3c7547f..00000000000 --- a/contrib/libunwind/src/ia64/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/contrib/libunwind/src/ia64/Ltables.c b/contrib/libunwind/src/ia64/Ltables.c deleted file mode 100644 index 876b0aac03d..00000000000 --- a/contrib/libunwind/src/ia64/Ltables.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gtables.c" -#endif diff --git a/contrib/libunwind/src/ia64/NOTES b/contrib/libunwind/src/ia64/NOTES deleted file mode 100644 index a5805e83456..00000000000 --- a/contrib/libunwind/src/ia64/NOTES +++ /dev/null @@ -1,65 +0,0 @@ -- the frame state consists of the following: - - - ip current instruction pointer - - sp current stack pointer value - - bsp current backing store pointer - - cfm current frame mask - - these are derived from the next younger (more deeply nested) frame - as follows: - - - ip == saved return-link (may be b0 or an alternate branch-reg) - - sp == if younger frame has a fixed-sized frame, sp + size-of-frame, - else saved sp - - cfm == saved ar.pfs - - bsp == if ar.bsp has been saved, saved ar.bsp, otherwise, - ar.bsp \ominus saved ar.pfs.pfm.sol - -The unwind cursor should represent the machine state as it existed at -the address contained in register ip. This state consists of the -*current* frame state and the save locations in the next younger -frame. - -An unwind script current takes the old save locations and updates them -for the next older frame. With the new setup, we need to update the -frame state first, without updating the other save locations. For this -to work, we need the following info: - - - save location of return-link - - save location of ar.pfs - - save location of bsp (if it has been saved) - - size of stack frame (fixed case) or save location of sp - - -setup: - - func: ... - ... - ... - br.call foo <-- call site - ... <-- ip - ... - -initial state: - - The unwind cursor represents the (preserved) machine state - as it existed at "ip". - - Evaluating the unwind descriptors for "ip" yields the following - info: - - - frame size at call site (or previous sp) - - what registers where saved where by func before - the call site was reached - - - Note that there is some procedure info that needs to be obtained - for the new "ip" which is contained in the unwind descriptors. - Specifically, the following is needed: - - - procedure's start address - - personality address - - pointer to language-specific data area - - This info is stored in a separate proc_info structure and needs - to be obtained right after running the unwind script for func. diff --git a/contrib/libunwind/src/ia64/dyn_info_list.S b/contrib/libunwind/src/ia64/dyn_info_list.S deleted file mode 100644 index 31265f66a06..00000000000 --- a/contrib/libunwind/src/ia64/dyn_info_list.S +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef UNW_REMOTE_ONLY - -/* - * Create a special unwind-table entry which makes it easy for an - * unwinder to locate the dynamic registration list. The special - * entry covers address range [0-0) and is therefore guaranteed to be - * the first in the unwind-table. - */ - .global _U_dyn_info_list - .hidden _U_dyn_info_list - - .section .IA_64.unwind_info,"a","progbits" -.info: data8 (1<<48) | 1 /* v1, length==1 (8-byte word) */ - data8 0 /* 8 empty .prologue directives (nops) */ - data8 0 /* personality routine (ignored) */ - string "dyn-list" /* lsda */ - data8 @gprel(_U_dyn_info_list) - - .section .IA_64.unwind, "a", "progbits" - data8 0, 0, @segrel(.info) - -#endif -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ia64/getcontext.S b/contrib/libunwind/src/ia64/getcontext.S deleted file mode 100644 index d8da732acc8..00000000000 --- a/contrib/libunwind/src/ia64/getcontext.S +++ /dev/null @@ -1,177 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "ucontext_i.h" - -#define GR(n) (SC_GR + (n)*8) -#define BR(n) (SC_BR + (n)*8) -#define FR(n) (SC_FR + (n)*16) - -/* This should be compatible to the libc's getcontext(), except that - the sc->sc_mask field is always cleared and that the name is - prefixed with _Uia64_ so we don't step on the application's - name-space. */ - - .align 32 - .protected _Uia64_getcontext - .global _Uia64_getcontext - .proc _Uia64_getcontext -_Uia64_getcontext: - .prologue - alloc rPFS = ar.pfs, 1, 0, 0, 0 // M2 - mov rPR = pr // I0, 2 cycles - add r2 = GR(1), in0 // I1 - ;; - - .save ar.unat, rUNAT - mov.m rUNAT = ar.unat // M2, 5 cycles - .body - st8.spill [r2] = r1, (SC_FLAGS - GR(1)) // M3 - dep.z rFLAGS = -1, IA64_SC_FLAG_SYNCHRONOUS_BIT, 1 // I0, 1 cycle - ;; - - mov.m rRSC = ar.rsc // M2, 12 cyc. - st8 [r2] = rFLAGS, (SC_PR - SC_FLAGS) // M3 - add r3 = FR(2), in0 - ;; - - mov.m rBSP = ar.bsp // M2, 12 cyc. - st8 [r2] = rPR, (GR(12) - SC_PR) // M3 - add r8 = FR(16), in0 - ;; - - mov.m rFPSR = ar.fpsr // M2, 12 cyc. - st8.spill [r2] = r12, (GR(4) - GR(12)) // M3 - add r9 = FR(24), in0 - ;; - - stf.spill [r3] = f2 // M2 - stf.spill [r8] = f16 // M3 - add r3 = GR(7), in0 - ;; - - flushrs // M0 - stf.spill [r9] = f24, (FR(31) - FR(24)) // M2 - mov rB0 = b0 // I0, 2 cycles - ;; - - stf.spill [r9] = f31 // M2 - st8.spill [r2] = r4, (GR(5) - GR(4)) // M3, bank 1 - mov rB1 = b1 // I0, 2 cycles - ;; - -.mem.offset 0,0; st8.spill [r2] = r5, (GR(6) - GR(5)) // M4, bank 0 -.mem.offset 8,0; st8.spill [r3] = r7, (BR(0) - GR(7)) // M3, bank 0 - mov rB2 = b2 // I0, 2 cycles - ;; - - st8.spill [r2] = r6, (BR(1) - GR(6)) // M2, bank 1 - st8 [r3] = rB0, (BR(4) - BR(0)) // M3, bank 1 - mov rB4 = b4 // I0, 2 cycles - ;; - - mov.m rNAT = ar.unat // M2, 5 cycles - st8 [r2] = rB1, (BR(2) - BR(1)) // M3, bank 0 - mov rB3 = b3 - ;; - - st8 [r2] = rB2, (BR(3) - BR(2)) // M2, bank 1 - st8 [r3] = rB4, (SC_LC - BR(4)) // M3, bank 1 - mov rB5 = b5 // I0, 2 cycles - ;; - - and rTMP = ~0x3, rRSC // M0 - add rPOS = GR(0), in0 // rPOS <- &sc_gr[0] // M1 - mov.i rLC = ar.lc // I0, 2 cycles - ;; - - mov.m ar.rsc = rTMP // put RSE into lazy mode // M2, ? cycles - st8 [r2] = rB3, (BR(5) - BR(3)) // M3, bank 0 - extr.u rPOS = rPOS, 3, 6 // get NaT bitnr for r0 // I0 - ;; - - mov.m rRNAT = ar.rnat // M2, 5 cycles - st8 [r2] = rB5, (SC_PFS - BR(5)) // M3, bank 0 - sub rCPOS = 64, rPOS // I0 - ;; - - st8 [r2] = rPFS, (SC_UNAT - SC_PFS) // M2 - st8 [r3] = rLC, (SC_BSP - SC_LC) // M3 - shr.u rTMP = rNAT, rPOS // I0, 3 cycles - ;; - - st8 [r2] = rUNAT, (SC_FPSR - SC_UNAT) // M2 - st8 [r3] = rBSP // M3 - add r8 = FR(3), in0 - ;; - - st8 [r2] = rFPSR, (SC_RNAT - SC_FPSR) // M2 - stf.spill [r8] = f3, (FR(4) - FR(3)) // M3 - add r9 = FR(5), in0 - ;; - - stf.spill [r8] = f4, (FR(17) - FR(4)) // M2 - stf.spill [r9] = f5, (FR(19) - FR(5)) // M3 - shl rNAT = rNAT, rCPOS // I0, 3 cycles - ;; - - st8 [r2] = rRNAT, (SC_NAT - SC_RNAT) // M2 - stf.spill [r8] = f17, (FR(18) - FR(17)) // M3 - nop.i 0 - ;; - - stf.spill [r8] = f18, (FR(20) - FR(18)) // M2 - stf.spill [r9] = f19, (FR(21) - FR(19)) // M3 - nop.i 0 - ;; - - stf.spill [r8] = f20, (FR(22) - FR(20)) // M2 - stf.spill [r9] = f21, (FR(23) - FR(21)) // M3 - or rNAT = rNAT, rTMP // I0 - ;; - - st8 [r2] = rNAT // M2 - stf.spill [r8] = f22, (FR(25) - FR(22)) // M3 - ;; - stf.spill [r9] = f23, (FR(26) - FR(23)) // M2 - stf.spill [r8] = f25, (FR(27) - FR(25)) // M3 - ;; - stf.spill [r9] = f26, (FR(28) - FR(26)) // M2 - stf.spill [r8] = f27, (FR(29) - FR(27)) // M3 - ;; - mov.m ar.rsc = rRSC // restore RSE mode // M2 - stf.spill [r9] = f28, (FR(30) - FR(28)) // M3 - ;; - mov.m ar.unat = rUNAT // restore caller's UNaT // M2 - stf.spill [r8] = f29 // M3 - ;; - stf.spill [r9] = f30 // M2 - mov r8 = 0 - br.ret.sptk.many rp - .endp _Uia64_getcontext -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ia64/init.h b/contrib/libunwind/src/ia64/init.h deleted file mode 100644 index 6628a1d8882..00000000000 --- a/contrib/libunwind/src/ia64/init.h +++ /dev/null @@ -1,132 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static ALWAYS_INLINE int -common_init (struct cursor *c, unw_word_t sp, unw_word_t bsp) -{ - unw_word_t bspstore, rbs_base; - int ret; - - if (c->as->caching_policy != UNW_CACHE_NONE) - /* ensure cache doesn't have any stale contents: */ - ia64_validate_cache (c->as, c->as_arg); - - c->cfm_loc = IA64_REG_LOC (c, UNW_IA64_CFM); - c->loc[IA64_REG_BSP] = IA64_NULL_LOC; - c->loc[IA64_REG_BSPSTORE] = IA64_REG_LOC (c, UNW_IA64_AR_BSPSTORE); - c->loc[IA64_REG_PFS] = IA64_REG_LOC (c, UNW_IA64_AR_PFS); - c->loc[IA64_REG_RNAT] = IA64_REG_LOC (c, UNW_IA64_AR_RNAT); - c->loc[IA64_REG_IP] = IA64_REG_LOC (c, UNW_IA64_IP); - c->loc[IA64_REG_PRI_UNAT_MEM] = IA64_NULL_LOC; /* no primary UNaT location */ - c->loc[IA64_REG_UNAT] = IA64_REG_LOC (c, UNW_IA64_AR_UNAT); - c->loc[IA64_REG_PR] = IA64_REG_LOC (c, UNW_IA64_PR); - c->loc[IA64_REG_LC] = IA64_REG_LOC (c, UNW_IA64_AR_LC); - c->loc[IA64_REG_FPSR] = IA64_REG_LOC (c, UNW_IA64_AR_FPSR); - - c->loc[IA64_REG_R4] = IA64_REG_LOC (c, UNW_IA64_GR + 4); - c->loc[IA64_REG_R5] = IA64_REG_LOC (c, UNW_IA64_GR + 5); - c->loc[IA64_REG_R6] = IA64_REG_LOC (c, UNW_IA64_GR + 6); - c->loc[IA64_REG_R7] = IA64_REG_LOC (c, UNW_IA64_GR + 7); - - c->loc[IA64_REG_NAT4] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 4, &c->nat_bitnr[0]); - c->loc[IA64_REG_NAT5] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 5, &c->nat_bitnr[1]); - c->loc[IA64_REG_NAT6] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 6, &c->nat_bitnr[2]); - c->loc[IA64_REG_NAT7] = IA64_REG_NAT_LOC (c, UNW_IA64_NAT + 7, &c->nat_bitnr[3]); - - c->loc[IA64_REG_B1] = IA64_REG_LOC (c, UNW_IA64_BR + 1); - c->loc[IA64_REG_B2] = IA64_REG_LOC (c, UNW_IA64_BR + 2); - c->loc[IA64_REG_B3] = IA64_REG_LOC (c, UNW_IA64_BR + 3); - c->loc[IA64_REG_B4] = IA64_REG_LOC (c, UNW_IA64_BR + 4); - c->loc[IA64_REG_B5] = IA64_REG_LOC (c, UNW_IA64_BR + 5); - - c->loc[IA64_REG_F2] = IA64_FPREG_LOC (c, UNW_IA64_FR + 2); - c->loc[IA64_REG_F3] = IA64_FPREG_LOC (c, UNW_IA64_FR + 3); - c->loc[IA64_REG_F4] = IA64_FPREG_LOC (c, UNW_IA64_FR + 4); - c->loc[IA64_REG_F5] = IA64_FPREG_LOC (c, UNW_IA64_FR + 5); - c->loc[IA64_REG_F16] = IA64_FPREG_LOC (c, UNW_IA64_FR + 16); - c->loc[IA64_REG_F17] = IA64_FPREG_LOC (c, UNW_IA64_FR + 17); - c->loc[IA64_REG_F18] = IA64_FPREG_LOC (c, UNW_IA64_FR + 18); - c->loc[IA64_REG_F19] = IA64_FPREG_LOC (c, UNW_IA64_FR + 19); - c->loc[IA64_REG_F20] = IA64_FPREG_LOC (c, UNW_IA64_FR + 20); - c->loc[IA64_REG_F21] = IA64_FPREG_LOC (c, UNW_IA64_FR + 21); - c->loc[IA64_REG_F22] = IA64_FPREG_LOC (c, UNW_IA64_FR + 22); - c->loc[IA64_REG_F23] = IA64_FPREG_LOC (c, UNW_IA64_FR + 23); - c->loc[IA64_REG_F24] = IA64_FPREG_LOC (c, UNW_IA64_FR + 24); - c->loc[IA64_REG_F25] = IA64_FPREG_LOC (c, UNW_IA64_FR + 25); - c->loc[IA64_REG_F26] = IA64_FPREG_LOC (c, UNW_IA64_FR + 26); - c->loc[IA64_REG_F27] = IA64_FPREG_LOC (c, UNW_IA64_FR + 27); - c->loc[IA64_REG_F28] = IA64_FPREG_LOC (c, UNW_IA64_FR + 28); - c->loc[IA64_REG_F29] = IA64_FPREG_LOC (c, UNW_IA64_FR + 29); - c->loc[IA64_REG_F30] = IA64_FPREG_LOC (c, UNW_IA64_FR + 30); - c->loc[IA64_REG_F31] = IA64_FPREG_LOC (c, UNW_IA64_FR + 31); - - ret = ia64_get (c, c->loc[IA64_REG_IP], &c->ip); - if (ret < 0) - return ret; - - ret = ia64_get (c, c->cfm_loc, &c->cfm); - if (ret < 0) - return ret; - - ret = ia64_get (c, c->loc[IA64_REG_PR], &c->pr); - if (ret < 0) - return ret; - - c->sp = c->psp = sp; - c->bsp = bsp; - - ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &bspstore); - if (ret < 0) - return ret; - - c->rbs_curr = c->rbs_left_edge = 0; - - /* Try to find a base of the register backing-store. We may default - to a reasonable value (e.g., half the address-space down from - bspstore). If the BSPSTORE looks corrupt, we fail. */ - if ((ret = rbs_get_base (c, bspstore, &rbs_base)) < 0) - return ret; - - c->rbs_area[0].end = bspstore; - c->rbs_area[0].size = bspstore - rbs_base; - c->rbs_area[0].rnat_loc = IA64_REG_LOC (c, UNW_IA64_AR_RNAT); - Debug (10, "initial rbs-area: [0x%llx-0x%llx), rnat@%s\n", - (long long) rbs_base, (long long) c->rbs_area[0].end, - ia64_strloc (c->rbs_area[0].rnat_loc)); - - c->pi.flags = 0; - - c->sigcontext_addr = 0; - c->abi_marker = 0; - c->last_abi_marker = 0; - - c->hint = 0; - c->prev_script = 0; - c->eh_valid_mask = 0; - c->pi_valid = 0; - return 0; -} diff --git a/contrib/libunwind/src/ia64/longjmp.S b/contrib/libunwind/src/ia64/longjmp.S deleted file mode 100644 index 2a2f286594b..00000000000 --- a/contrib/libunwind/src/ia64/longjmp.S +++ /dev/null @@ -1,42 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - - .global _UI_longjmp_cont - - .align 32 - .proc longjmp_continuation -longjmp_continuation: -_UI_longjmp_cont: // non-function label for {sig,}longjmp.c - .prologue - .save rp, r15 - .body - mov rp = r15 - mov r8 = r16 - br.sptk.many rp - .endp longjmp_continuation -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ia64/mk_Gcursor_i.c b/contrib/libunwind/src/ia64/mk_Gcursor_i.c deleted file mode 100644 index 67b14d52ba3..00000000000 --- a/contrib/libunwind/src/ia64/mk_Gcursor_i.c +++ /dev/null @@ -1,65 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Utility to generate cursor_i.h. */ - -#include "libunwind_i.h" - -#ifdef offsetof -# undef offsetof -#endif - -#define offsetof(type,field) ((char *) &((type *) 0)->field - (char *) 0) - -#define OFFSET(sym, offset) \ - asm volatile("\n->" #sym " %0" : : "i" (offset)) - -int -main (void) -{ - OFFSET("IP_OFF", offsetof (struct cursor, ip)); - OFFSET("PR_OFF", offsetof (struct cursor, pr)); - OFFSET("BSP_OFF", offsetof (struct cursor, bsp)); - OFFSET("PSP_OFF", offsetof (struct cursor, psp)); - OFFSET("PFS_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_PFS])); - OFFSET("RNAT_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_RNAT])); - OFFSET("UNAT_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_UNAT])); - OFFSET("LC_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_LC])); - OFFSET("FPSR_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_FPSR])); - OFFSET("B1_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_B1])); - OFFSET("B2_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_B2])); - OFFSET("B3_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_B3])); - OFFSET("B4_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_B4])); - OFFSET("B5_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_B5])); - OFFSET("F2_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_F2])); - OFFSET("F3_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_F3])); - OFFSET("F4_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_F4])); - OFFSET("F5_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_F5])); - OFFSET("FR_LOC_OFF", offsetof (struct cursor, loc[IA64_REG_F16])); - OFFSET("LOC_SIZE", - (offsetof (struct cursor, loc[1]) - offsetof (struct cursor, loc[0]))); - OFFSET("SIGCONTEXT_ADDR_OFF", offsetof (struct cursor, sigcontext_addr)); - return 0; -} diff --git a/contrib/libunwind/src/ia64/mk_Lcursor_i.c b/contrib/libunwind/src/ia64/mk_Lcursor_i.c deleted file mode 100644 index aee2e7eeb8d..00000000000 --- a/contrib/libunwind/src/ia64/mk_Lcursor_i.c +++ /dev/null @@ -1,2 +0,0 @@ -#define UNW_LOCAL_ONLY -#include "mk_Gcursor_i.c" diff --git a/contrib/libunwind/src/ia64/mk_cursor_i b/contrib/libunwind/src/ia64/mk_cursor_i deleted file mode 100755 index 9211f91bbbb..00000000000 --- a/contrib/libunwind/src/ia64/mk_cursor_i +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -test -z "$1" && exit 1 -echo "/* GENERATED */" -echo "#ifndef cursor_i_h" -echo "#define cursor_i_h" -sed -ne 's/^->"\(\S*\)" \(\d*\)/#define \1 \2/p' < $1 || exit $? -echo "#endif" diff --git a/contrib/libunwind/src/ia64/offsets.h b/contrib/libunwind/src/ia64/offsets.h deleted file mode 100644 index 5ab7f8b31e6..00000000000 --- a/contrib/libunwind/src/ia64/offsets.h +++ /dev/null @@ -1,137 +0,0 @@ -/* Linux-specific definitions: */ - -/* Define various structure offsets to simplify cross-compilation. */ - -/* The first three 64-bit words in a signal frame contain the signal - number, siginfo pointer, and sigcontext pointer passed to the - signal handler. We use this to locate the sigcontext pointer. */ - -#define LINUX_SIGFRAME_ARG2_OFF 0x10 - -#define LINUX_SC_FLAGS_OFF 0x000 -#define LINUX_SC_NAT_OFF 0x008 -#define LINUX_SC_STACK_OFF 0x010 -#define LINUX_SC_IP_OFF 0x028 -#define LINUX_SC_CFM_OFF 0x030 -#define LINUX_SC_UM_OFF 0x038 -#define LINUX_SC_AR_RSC_OFF 0x040 -#define LINUX_SC_AR_BSP_OFF 0x048 -#define LINUX_SC_AR_RNAT_OFF 0x050 -#define LINUX_SC_AR_CCV 0x058 -#define LINUX_SC_AR_UNAT_OFF 0x060 -#define LINUX_SC_AR_FPSR_OFF 0x068 -#define LINUX_SC_AR_PFS_OFF 0x070 -#define LINUX_SC_AR_LC_OFF 0x078 -#define LINUX_SC_PR_OFF 0x080 -#define LINUX_SC_BR_OFF 0x088 -#define LINUX_SC_GR_OFF 0x0c8 -#define LINUX_SC_FR_OFF 0x1d0 -#define LINUX_SC_RBS_BASE_OFF 0x9d0 -#define LINUX_SC_LOADRS_OFF 0x9d8 -#define LINUX_SC_AR_CSD_OFF 0x9e0 -#define LINUX_SC_AR_SSD_OFF 0x9e8 -#define LINUX_SC_MASK 0xa50 - -/* Layout of old Linux kernel interrupt frame (struct pt_regs). */ - -#define LINUX_OLD_PT_IPSR_OFF 0x000 -#define LINUX_OLD_PT_IIP_OFF 0x008 -#define LINUX_OLD_PT_IFS_OFF 0x010 -#define LINUX_OLD_PT_UNAT_OFF 0x018 -#define LINUX_OLD_PT_PFS_OFF 0x020 -#define LINUX_OLD_PT_RSC_OFF 0x028 -#define LINUX_OLD_PT_RNAT_OFF 0x030 -#define LINUX_OLD_PT_BSPSTORE_OFF 0x038 -#define LINUX_OLD_PT_PR_OFF 0x040 -#define LINUX_OLD_PT_B6_OFF 0x048 -#define LINUX_OLD_PT_LOADRS_OFF 0x050 -#define LINUX_OLD_PT_R1_OFF 0x058 -#define LINUX_OLD_PT_R2_OFF 0x060 -#define LINUX_OLD_PT_R3_OFF 0x068 -#define LINUX_OLD_PT_R12_OFF 0x070 -#define LINUX_OLD_PT_R13_OFF 0x078 -#define LINUX_OLD_PT_R14_OFF 0x080 -#define LINUX_OLD_PT_R15_OFF 0x088 -#define LINUX_OLD_PT_R8_OFF 0x090 -#define LINUX_OLD_PT_R9_OFF 0x098 -#define LINUX_OLD_PT_R10_OFF 0x0a0 -#define LINUX_OLD_PT_R11_OFF 0x0a8 -#define LINUX_OLD_PT_R16_OFF 0x0b0 -#define LINUX_OLD_PT_R17_OFF 0x0b8 -#define LINUX_OLD_PT_R18_OFF 0x0c0 -#define LINUX_OLD_PT_R19_OFF 0x0c8 -#define LINUX_OLD_PT_R20_OFF 0x0d0 -#define LINUX_OLD_PT_R21_OFF 0x0d8 -#define LINUX_OLD_PT_R22_OFF 0x0e0 -#define LINUX_OLD_PT_R23_OFF 0x0e8 -#define LINUX_OLD_PT_R24_OFF 0x0f0 -#define LINUX_OLD_PT_R25_OFF 0x0f8 -#define LINUX_OLD_PT_R26_OFF 0x100 -#define LINUX_OLD_PT_R27_OFF 0x108 -#define LINUX_OLD_PT_R28_OFF 0x110 -#define LINUX_OLD_PT_R29_OFF 0x118 -#define LINUX_OLD_PT_R30_OFF 0x120 -#define LINUX_OLD_PT_R31_OFF 0x128 -#define LINUX_OLD_PT_CCV_OFF 0x130 -#define LINUX_OLD_PT_FPSR_OFF 0x138 -#define LINUX_OLD_PT_B0_OFF 0x140 -#define LINUX_OLD_PT_B7_OFF 0x148 -#define LINUX_OLD_PT_F6_OFF 0x150 -#define LINUX_OLD_PT_F7_OFF 0x160 -#define LINUX_OLD_PT_F8_OFF 0x170 -#define LINUX_OLD_PT_F9_OFF 0x180 - -/* Layout of new Linux kernel interrupt frame (struct pt_regs). */ - -#define LINUX_PT_B6_OFF 0 -#define LINUX_PT_B7_OFF 8 -#define LINUX_PT_CSD_OFF 16 -#define LINUX_PT_SSD_OFF 24 -#define LINUX_PT_R8_OFF 32 -#define LINUX_PT_R9_OFF 40 -#define LINUX_PT_R10_OFF 48 -#define LINUX_PT_R11_OFF 56 -#define LINUX_PT_IPSR_OFF 64 -#define LINUX_PT_IIP_OFF 72 -#define LINUX_PT_IFS_OFF 80 -#define LINUX_PT_UNAT_OFF 88 -#define LINUX_PT_PFS_OFF 96 -#define LINUX_PT_RSC_OFF 104 -#define LINUX_PT_RNAT_OFF 112 -#define LINUX_PT_BSPSTORE_OFF 120 -#define LINUX_PT_PR_OFF 128 -#define LINUX_PT_B0_OFF 136 -#define LINUX_PT_LOADRS_OFF 144 -#define LINUX_PT_R1_OFF 152 -#define LINUX_PT_R12_OFF 160 -#define LINUX_PT_R13_OFF 168 -#define LINUX_PT_FPSR_OFF 176 -#define LINUX_PT_R15_OFF 184 -#define LINUX_PT_R14_OFF 192 -#define LINUX_PT_R2_OFF 200 -#define LINUX_PT_R3_OFF 208 -#define LINUX_PT_R16_OFF 216 -#define LINUX_PT_R17_OFF 224 -#define LINUX_PT_R18_OFF 232 -#define LINUX_PT_R19_OFF 240 -#define LINUX_PT_R20_OFF 248 -#define LINUX_PT_R21_OFF 256 -#define LINUX_PT_R22_OFF 264 -#define LINUX_PT_R23_OFF 272 -#define LINUX_PT_R24_OFF 280 -#define LINUX_PT_R25_OFF 288 -#define LINUX_PT_R26_OFF 296 -#define LINUX_PT_R27_OFF 304 -#define LINUX_PT_R28_OFF 312 -#define LINUX_PT_R29_OFF 320 -#define LINUX_PT_R30_OFF 328 -#define LINUX_PT_R31_OFF 336 -#define LINUX_PT_CCV_OFF 344 -#define LINUX_PT_F6_OFF 352 -#define LINUX_PT_F7_OFF 368 -#define LINUX_PT_F8_OFF 384 -#define LINUX_PT_F9_OFF 400 -#define LINUX_PT_F10_OFF 416 -#define LINUX_PT_F11_OFF 432 - -#define LINUX_PT_P_NONSYS 5 /* must match pNonSys in entry.h */ diff --git a/contrib/libunwind/src/ia64/regname.c b/contrib/libunwind/src/ia64/regname.c deleted file mode 100644 index 8753e5208ea..00000000000 --- a/contrib/libunwind/src/ia64/regname.c +++ /dev/null @@ -1,189 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Logically, we like to think of the stack as a contiguous region of -memory. Unfortunately, this logical view doesn't work for the -register backing store, because the RSE is an asynchronous engine and -because UNIX/Linux allow for stack-switching via sigaltstack(2). -Specifically, this means that any given stacked register may or may -not be backed up by memory in the current stack. If not, then the -backing memory may be found in any of the "more inner" (younger) -stacks. The routines in this file help manage the discontiguous -nature of the register backing store. The routines are completely -independent of UNIX/Linux, but each stack frame that switches the -backing store is expected to reserve 4 words for use by libunwind. For -example, in the Linux sigcontext, sc_fr[0] and sc_fr[1] serve this -purpose. */ - -#include "libunwind_i.h" - -/* Maintain the register names as a single string to keep the number - of dynamic relocations in the shared object to a minimum. */ - -#define regname_len 9 -#define regname_str \ - "r0\0\0\0\0\0\0\0r1\0\0\0\0\0\0\0r2\0\0\0\0\0\0\0r3\0\0\0\0\0\0\0" \ - "r4\0\0\0\0\0\0\0r5\0\0\0\0\0\0\0r6\0\0\0\0\0\0\0r7\0\0\0\0\0\0\0" \ - "r8\0\0\0\0\0\0\0r9\0\0\0\0\0\0\0r10\0\0\0\0\0\0r11\0\0\0\0\0\0" \ - "r12\0\0\0\0\0\0r13\0\0\0\0\0\0r14\0\0\0\0\0\0r15\0\0\0\0\0\0" \ - "r16\0\0\0\0\0\0r17\0\0\0\0\0\0r18\0\0\0\0\0\0r19\0\0\0\0\0\0" \ - "r20\0\0\0\0\0\0r21\0\0\0\0\0\0r22\0\0\0\0\0\0r23\0\0\0\0\0\0" \ - "r24\0\0\0\0\0\0r25\0\0\0\0\0\0r26\0\0\0\0\0\0r27\0\0\0\0\0\0" \ - "r28\0\0\0\0\0\0r29\0\0\0\0\0\0r30\0\0\0\0\0\0r31\0\0\0\0\0\0" \ - "r32\0\0\0\0\0\0r33\0\0\0\0\0\0r34\0\0\0\0\0\0r35\0\0\0\0\0\0" \ - "r36\0\0\0\0\0\0r37\0\0\0\0\0\0r38\0\0\0\0\0\0r39\0\0\0\0\0\0" \ - "r40\0\0\0\0\0\0r41\0\0\0\0\0\0r42\0\0\0\0\0\0r43\0\0\0\0\0\0" \ - "r44\0\0\0\0\0\0r45\0\0\0\0\0\0r46\0\0\0\0\0\0r47\0\0\0\0\0\0" \ - "r48\0\0\0\0\0\0r49\0\0\0\0\0\0r50\0\0\0\0\0\0r51\0\0\0\0\0\0" \ - "r52\0\0\0\0\0\0r53\0\0\0\0\0\0r54\0\0\0\0\0\0r55\0\0\0\0\0\0" \ - "r56\0\0\0\0\0\0r57\0\0\0\0\0\0r58\0\0\0\0\0\0r59\0\0\0\0\0\0" \ - "r60\0\0\0\0\0\0r61\0\0\0\0\0\0r62\0\0\0\0\0\0r63\0\0\0\0\0\0" \ - "r64\0\0\0\0\0\0r65\0\0\0\0\0\0r66\0\0\0\0\0\0r67\0\0\0\0\0\0" \ - "r68\0\0\0\0\0\0r69\0\0\0\0\0\0r70\0\0\0\0\0\0r71\0\0\0\0\0\0" \ - "r72\0\0\0\0\0\0r73\0\0\0\0\0\0r74\0\0\0\0\0\0r75\0\0\0\0\0\0" \ - "r76\0\0\0\0\0\0r77\0\0\0\0\0\0r78\0\0\0\0\0\0r79\0\0\0\0\0\0" \ - "r80\0\0\0\0\0\0r81\0\0\0\0\0\0r82\0\0\0\0\0\0r83\0\0\0\0\0\0" \ - "r84\0\0\0\0\0\0r85\0\0\0\0\0\0r86\0\0\0\0\0\0r87\0\0\0\0\0\0" \ - "r88\0\0\0\0\0\0r89\0\0\0\0\0\0r90\0\0\0\0\0\0r91\0\0\0\0\0\0" \ - "r92\0\0\0\0\0\0r93\0\0\0\0\0\0r94\0\0\0\0\0\0r95\0\0\0\0\0\0" \ - "r96\0\0\0\0\0\0r97\0\0\0\0\0\0r98\0\0\0\0\0\0r99\0\0\0\0\0\0" \ - "r100\0\0\0\0\0r101\0\0\0\0\0r102\0\0\0\0\0r103\0\0\0\0\0" \ - "r104\0\0\0\0\0r105\0\0\0\0\0r106\0\0\0\0\0r107\0\0\0\0\0" \ - "r108\0\0\0\0\0r109\0\0\0\0\0r110\0\0\0\0\0r111\0\0\0\0\0" \ - "r112\0\0\0\0\0r113\0\0\0\0\0r114\0\0\0\0\0r115\0\0\0\0\0" \ - "r116\0\0\0\0\0r117\0\0\0\0\0r118\0\0\0\0\0r119\0\0\0\0\0" \ - "r120\0\0\0\0\0r121\0\0\0\0\0r122\0\0\0\0\0r123\0\0\0\0\0" \ - "r124\0\0\0\0\0r125\0\0\0\0\0r126\0\0\0\0\0r127\0\0\0\0\0" \ - "nat0\0\0\0\0\0nat1\0\0\0\0\0nat2\0\0\0\0\0nat3\0\0\0\0\0" \ - "nat4\0\0\0\0\0nat5\0\0\0\0\0nat6\0\0\0\0\0nat7\0\0\0\0\0" \ - "nat8\0\0\0\0\0nat9\0\0\0\0\0nat10\0\0\0\0nat11\0\0\0\0" \ - "nat12\0\0\0\0nat13\0\0\0\0nat14\0\0\0\0nat15\0\0\0\0" \ - "nat16\0\0\0\0nat17\0\0\0\0nat18\0\0\0\0nat19\0\0\0\0" \ - "nat20\0\0\0\0nat21\0\0\0\0nat22\0\0\0\0nat23\0\0\0\0" \ - "nat24\0\0\0\0nat25\0\0\0\0nat26\0\0\0\0nat27\0\0\0\0" \ - "nat28\0\0\0\0nat29\0\0\0\0nat30\0\0\0\0nat31\0\0\0\0" \ - "nat32\0\0\0\0nat33\0\0\0\0nat34\0\0\0\0nat35\0\0\0\0" \ - "nat36\0\0\0\0nat37\0\0\0\0nat38\0\0\0\0nat39\0\0\0\0" \ - "nat40\0\0\0\0nat41\0\0\0\0nat42\0\0\0\0nat43\0\0\0\0" \ - "nat44\0\0\0\0nat45\0\0\0\0nat46\0\0\0\0nat47\0\0\0\0" \ - "nat48\0\0\0\0nat49\0\0\0\0nat50\0\0\0\0nat51\0\0\0\0" \ - "nat52\0\0\0\0nat53\0\0\0\0nat54\0\0\0\0nat55\0\0\0\0" \ - "nat56\0\0\0\0nat57\0\0\0\0nat58\0\0\0\0nat59\0\0\0\0" \ - "nat60\0\0\0\0nat61\0\0\0\0nat62\0\0\0\0nat63\0\0\0\0" \ - "nat64\0\0\0\0nat65\0\0\0\0nat66\0\0\0\0nat67\0\0\0\0" \ - "nat68\0\0\0\0nat69\0\0\0\0nat70\0\0\0\0nat71\0\0\0\0" \ - "nat72\0\0\0\0nat73\0\0\0\0nat74\0\0\0\0nat75\0\0\0\0" \ - "nat76\0\0\0\0nat77\0\0\0\0nat78\0\0\0\0nat79\0\0\0\0" \ - "nat80\0\0\0\0nat81\0\0\0\0nat82\0\0\0\0nat83\0\0\0\0" \ - "nat84\0\0\0\0nat85\0\0\0\0nat86\0\0\0\0nat87\0\0\0\0" \ - "nat88\0\0\0\0nat89\0\0\0\0nat90\0\0\0\0nat91\0\0\0\0" \ - "nat92\0\0\0\0nat93\0\0\0\0nat94\0\0\0\0nat95\0\0\0\0" \ - "nat96\0\0\0\0nat97\0\0\0\0nat98\0\0\0\0nat99\0\0\0\0" \ - "nat100\0\0\0nat101\0\0\0nat102\0\0\0nat103\0\0\0" \ - "nat104\0\0\0nat105\0\0\0nat106\0\0\0nat107\0\0\0" \ - "nat108\0\0\0nat109\0\0\0nat110\0\0\0nat111\0\0\0" \ - "nat112\0\0\0nat113\0\0\0nat114\0\0\0nat115\0\0\0" \ - "nat116\0\0\0nat117\0\0\0nat118\0\0\0nat119\0\0\0" \ - "nat120\0\0\0nat121\0\0\0nat122\0\0\0nat123\0\0\0" \ - "nat124\0\0\0nat125\0\0\0nat126\0\0\0nat127\0\0\0" \ - "f0\0\0\0\0\0\0\0f1\0\0\0\0\0\0\0f2\0\0\0\0\0\0\0f3\0\0\0\0\0\0\0" \ - "f4\0\0\0\0\0\0\0f5\0\0\0\0\0\0\0f6\0\0\0\0\0\0\0f7\0\0\0\0\0\0\0" \ - "f8\0\0\0\0\0\0\0f9\0\0\0\0\0\0\0f10\0\0\0\0\0\0f11\0\0\0\0\0\0" \ - "f12\0\0\0\0\0\0f13\0\0\0\0\0\0f14\0\0\0\0\0\0f15\0\0\0\0\0\0" \ - "f16\0\0\0\0\0\0f17\0\0\0\0\0\0f18\0\0\0\0\0\0f19\0\0\0\0\0\0" \ - "f20\0\0\0\0\0\0f21\0\0\0\0\0\0f22\0\0\0\0\0\0f23\0\0\0\0\0\0" \ - "f24\0\0\0\0\0\0f25\0\0\0\0\0\0f26\0\0\0\0\0\0f27\0\0\0\0\0\0" \ - "f28\0\0\0\0\0\0f29\0\0\0\0\0\0f30\0\0\0\0\0\0f31\0\0\0\0\0\0" \ - "f32\0\0\0\0\0\0f33\0\0\0\0\0\0f34\0\0\0\0\0\0f35\0\0\0\0\0\0" \ - "f36\0\0\0\0\0\0f37\0\0\0\0\0\0f38\0\0\0\0\0\0f39\0\0\0\0\0\0" \ - "f40\0\0\0\0\0\0f41\0\0\0\0\0\0f42\0\0\0\0\0\0f43\0\0\0\0\0\0" \ - "f44\0\0\0\0\0\0f45\0\0\0\0\0\0f46\0\0\0\0\0\0f47\0\0\0\0\0\0" \ - "f48\0\0\0\0\0\0f49\0\0\0\0\0\0f50\0\0\0\0\0\0f51\0\0\0\0\0\0" \ - "f52\0\0\0\0\0\0f53\0\0\0\0\0\0f54\0\0\0\0\0\0f55\0\0\0\0\0\0" \ - "f56\0\0\0\0\0\0f57\0\0\0\0\0\0f58\0\0\0\0\0\0f59\0\0\0\0\0\0" \ - "f60\0\0\0\0\0\0f61\0\0\0\0\0\0f62\0\0\0\0\0\0f63\0\0\0\0\0\0" \ - "f64\0\0\0\0\0\0f65\0\0\0\0\0\0f66\0\0\0\0\0\0f67\0\0\0\0\0\0" \ - "f68\0\0\0\0\0\0f69\0\0\0\0\0\0f70\0\0\0\0\0\0f71\0\0\0\0\0\0" \ - "f72\0\0\0\0\0\0f73\0\0\0\0\0\0f74\0\0\0\0\0\0f75\0\0\0\0\0\0" \ - "f76\0\0\0\0\0\0f77\0\0\0\0\0\0f78\0\0\0\0\0\0f79\0\0\0\0\0\0" \ - "f80\0\0\0\0\0\0f81\0\0\0\0\0\0f82\0\0\0\0\0\0f83\0\0\0\0\0\0" \ - "f84\0\0\0\0\0\0f85\0\0\0\0\0\0f86\0\0\0\0\0\0f87\0\0\0\0\0\0" \ - "f88\0\0\0\0\0\0f89\0\0\0\0\0\0f90\0\0\0\0\0\0f91\0\0\0\0\0\0" \ - "f92\0\0\0\0\0\0f93\0\0\0\0\0\0f94\0\0\0\0\0\0f95\0\0\0\0\0\0" \ - "f96\0\0\0\0\0\0f97\0\0\0\0\0\0f98\0\0\0\0\0\0f99\0\0\0\0\0\0" \ - "f100\0\0\0\0\0f101\0\0\0\0\0f102\0\0\0\0\0f103\0\0\0\0\0" \ - "f104\0\0\0\0\0f105\0\0\0\0\0f106\0\0\0\0\0f107\0\0\0\0\0" \ - "f108\0\0\0\0\0f109\0\0\0\0\0f110\0\0\0\0\0f111\0\0\0\0\0" \ - "f112\0\0\0\0\0f113\0\0\0\0\0f114\0\0\0\0\0f115\0\0\0\0\0" \ - "f116\0\0\0\0\0f117\0\0\0\0\0f118\0\0\0\0\0f119\0\0\0\0\0" \ - "f120\0\0\0\0\0f121\0\0\0\0\0f122\0\0\0\0\0f123\0\0\0\0\0" \ - "f124\0\0\0\0\0f125\0\0\0\0\0f126\0\0\0\0\0f127\0\0\0\0\0" \ - "ar0\0\0\0\0\0\0ar1\0\0\0\0\0\0ar2\0\0\0\0\0\0ar3\0\0\0\0\0\0" \ - "ar4\0\0\0\0\0\0ar5\0\0\0\0\0\0ar6\0\0\0\0\0\0ar7\0\0\0\0\0\0" \ - "ar8\0\0\0\0\0\0ar9\0\0\0\0\0\0ar10\0\0\0\0\0ar11\0\0\0\0\0" \ - "ar12\0\0\0\0\0ar13\0\0\0\0\0ar14\0\0\0\0\0ar15\0\0\0\0\0" \ - "rsc\0\0\0\0\0\0bsp\0\0\0\0\0\0bspstore\0rnat\0\0\0\0\0" \ - "ar20\0\0\0\0\0ar21\0\0\0\0\0ar22\0\0\0\0\0ar23\0\0\0\0\0" \ - "ar24\0\0\0\0\0ar25\0\0\0\0\0ar26\0\0\0\0\0ar27\0\0\0\0\0" \ - "ar28\0\0\0\0\0ar29\0\0\0\0\0ar30\0\0\0\0\0ar31\0\0\0\0\0" \ - "ccv\0\0\0\0\0\0ar33\0\0\0\0\0ar34\0\0\0\0\0ar35\0\0\0\0\0" \ - "unat\0\0\0\0\0ar37\0\0\0\0\0ar38\0\0\0\0\0ar39\0\0\0\0\0" \ - "fpsr\0\0\0\0\0ar41\0\0\0\0\0ar42\0\0\0\0\0ar43\0\0\0\0\0" \ - "ar44\0\0\0\0\0ar45\0\0\0\0\0ar46\0\0\0\0\0ar47\0\0\0\0\0" \ - "ar48\0\0\0\0\0ar49\0\0\0\0\0ar50\0\0\0\0\0ar51\0\0\0\0\0" \ - "ar52\0\0\0\0\0ar53\0\0\0\0\0ar54\0\0\0\0\0ar55\0\0\0\0\0" \ - "ar56\0\0\0\0\0ar57\0\0\0\0\0ar58\0\0\0\0\0ar59\0\0\0\0\0" \ - "ar60\0\0\0\0\0ar61\0\0\0\0\0ar62\0\0\0\0\0ar63\0\0\0\0\0" \ - "pfs\0\0\0\0\0\0lc\0\0\0\0\0\0\0ec\0\0\0\0\0\0\0ar67\0\0\0\0\0" \ - "ar68\0\0\0\0\0ar69\0\0\0\0\0ar70\0\0\0\0\0ar71\0\0\0\0\0" \ - "ar72\0\0\0\0\0ar73\0\0\0\0\0ar74\0\0\0\0\0ar75\0\0\0\0\0" \ - "ar76\0\0\0\0\0ar77\0\0\0\0\0ar78\0\0\0\0\0ar79\0\0\0\0\0" \ - "ar80\0\0\0\0\0ar81\0\0\0\0\0ar82\0\0\0\0\0ar83\0\0\0\0\0" \ - "ar84\0\0\0\0\0ar85\0\0\0\0\0ar86\0\0\0\0\0ar87\0\0\0\0\0" \ - "ar88\0\0\0\0\0ar89\0\0\0\0\0ar90\0\0\0\0\0ar91\0\0\0\0\0" \ - "ar92\0\0\0\0\0ar93\0\0\0\0\0ar94\0\0\0\0\0ar95\0\0\0\0\0" \ - "ar96\0\0\0\0\0ar97\0\0\0\0\0ar98\0\0\0\0\0ar99\0\0\0\0\0" \ - "ar100\0\0\0\0ar101\0\0\0\0ar102\0\0\0\0ar103\0\0\0\0" \ - "ar104\0\0\0\0ar105\0\0\0\0ar106\0\0\0\0ar107\0\0\0\0" \ - "ar108\0\0\0\0ar109\0\0\0\0ar110\0\0\0\0ar111\0\0\0\0" \ - "ar112\0\0\0\0ar113\0\0\0\0ar114\0\0\0\0ar115\0\0\0\0" \ - "ar116\0\0\0\0ar117\0\0\0\0ar118\0\0\0\0ar119\0\0\0\0" \ - "ar120\0\0\0\0ar121\0\0\0\0ar122\0\0\0\0ar123\0\0\0\0" \ - "ar124\0\0\0\0ar125\0\0\0\0ar126\0\0\0\0ar127\0\0\0\0" \ - "rp\0\0\0\0\0\0\0b1\0\0\0\0\0\0\0b2\0\0\0\0\0\0\0b3\0\0\0\0\0\0\0" \ - "b4\0\0\0\0\0\0\0b5\0\0\0\0\0\0\0b6\0\0\0\0\0\0\0b7\0\0\0\0\0\0\0" \ - "pr\0\0\0\0\0\0\0cfm\0\0\0\0\0\0bsp\0\0\0\0\0\0ip\0\0\0\0\0\0\0" \ - "sp\0\0\0\0\0\0\0" - -#define NREGS ((int) (sizeof (regname_str) - 1) / regname_len) - -PROTECTED const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < NREGS) - return regname_str + reg * regname_len; - else - return "???"; -} diff --git a/contrib/libunwind/src/ia64/regs.h b/contrib/libunwind/src/ia64/regs.h deleted file mode 100644 index a22a818776f..00000000000 --- a/contrib/libunwind/src/ia64/regs.h +++ /dev/null @@ -1,73 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -/* Apply rotation to a general register. REG must be in the range 0-127. */ - -static inline int -rotate_gr (struct cursor *c, int reg) -{ - unsigned int rrb_gr, sor; - int preg; - - sor = 8 * ((c->cfm >> 14) & 0xf); - rrb_gr = (c->cfm >> 18) & 0x7f; - - if ((unsigned) (reg - 32) >= sor) - preg = reg; - else - { - preg = reg + rrb_gr; /* apply rotation */ - if ((unsigned) (preg - 32) >= sor) - preg -= sor; /* wrap around */ - } - if (sor) - Debug (15, "sor=%u rrb.gr=%u, r%d -> r%d\n", sor, rrb_gr, reg, preg); - return preg; -} - -/* Apply rotation to a floating-point register. The number REG must - be in the range of 0-127. */ - -static inline int -rotate_fr (struct cursor *c, int reg) -{ - unsigned int rrb_fr; - int preg; - - rrb_fr = (c->cfm >> 25) & 0x7f; - if (reg < 32) - preg = reg; /* register not part of the rotating partition */ - else - { - preg = reg + rrb_fr; /* apply rotation */ - if (preg > 127) - preg -= 96; /* wrap around */ - } - if (rrb_fr) - Debug (15, "rrb.fr=%u, f%d -> f%d\n", rrb_fr, reg, preg); - return preg; -} diff --git a/contrib/libunwind/src/ia64/setjmp.S b/contrib/libunwind/src/ia64/setjmp.S deleted file mode 100644 index 384615b840e..00000000000 --- a/contrib/libunwind/src/ia64/setjmp.S +++ /dev/null @@ -1,51 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "jmpbuf.h" - - .align 32 - - .global _setjmp - - .proc _setjmp - -_setjmp: - mov r2 = ar.bsp - st8 [r32] = r12 // jmp_buf[JB_SP] = sp - mov r3 = rp - - adds r16 = JB_RP*8, r32 - adds r17 = JB_BSP*8, r32 - mov r8 = 0 - ;; - st8 [r16] = r3 // jmp_buf[JB_RP] = rp - st8 [r17] = r2 // jmp_buf[JB_BSP] = bsp - br.ret.sptk.many rp - - .endp _setjmp -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ia64/siglongjmp.S b/contrib/libunwind/src/ia64/siglongjmp.S deleted file mode 100644 index d77b43753bb..00000000000 --- a/contrib/libunwind/src/ia64/siglongjmp.S +++ /dev/null @@ -1,69 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#define SIG_SETMASK 2 - - .global _UI_siglongjmp_cont - .global sigprocmask - - .align 32 - .proc siglongjmp_continuation -siglongjmp_continuation: -_UI_siglongjmp_cont: // non-function label for siglongjmp.c - .prologue - .save rp, r15 - .body - nop 0 - nop 0 - br.call.sptk.many b6 = .next - ;; - .prologue - .save ar.pfs, r33 -.next: alloc loc1 = ar.pfs, 0, 3, 3, 0 - /* - * Note: we can use the scratch stack are because the caller - * of sigsetjmp() by definition is not a leaf-procedure. - */ - st8 [sp] = r17 // store signal mask - .save rp, loc0 - mov loc0 = r15 // final continuation point - ;; - .body - mov loc2 = r16 // value to return in r8 - - mov out0 = SIG_SETMASK - mov out1 = sp - mov out2 = r0 - br.call.sptk.many rp = sigprocmask - ;; - mov rp = loc0 - mov ar.pfs = loc1 - mov r8 = loc2 - br.ret.sptk.many rp - .endp siglongjmp_continuation -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ia64/sigsetjmp.S b/contrib/libunwind/src/ia64/sigsetjmp.S deleted file mode 100644 index 02f7af4b377..00000000000 --- a/contrib/libunwind/src/ia64/sigsetjmp.S +++ /dev/null @@ -1,69 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "jmpbuf.h" - -#define SIG_BLOCK 0 - - .align 32 - - .global __sigsetjmp - .global sigprocmask - - .proc __sigsetjmp - -__sigsetjmp: - .prologue - .save ar.pfs, r35 - alloc loc1 = ar.pfs, 2, 3, 3, 0 - add out2 = JB_MASK*8, in0 - .save rp, loc0 - mov loc0 = rp - mov out0 = SIG_BLOCK - .body - ;; - cmp.ne p6, p0 = in1, r0 - mov out1 = r0 - mov loc2 = ar.bsp -(p6) br.call.sptk.many rp = sigprocmask // sigjmp_buf[JB_MASK] = sigmask - ;; - - add r16 = JB_MASK_SAVED*8, in0 - st8 [in0] = sp, (JB_RP-JB_SP)*8 // sigjmp_buf[JB_SP] = sp - mov r8 = 0 - ;; - st8 [in0] = loc0, (JB_BSP-JB_RP)*8 // sigjmp_buf[JB_RP] = rp - st8 [r16] = in1 // sigjmp_buf[JB_MASK_SAVED] = savemask - mov rp = loc0 - ;; - st8 [in0] = loc2 // sigjmp_buf[JB_BSP] = bsp - mov.i ar.pfs = loc1 - br.ret.sptk.many rp - - .endp __sigsetjmp -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ia64/ucontext_i.h b/contrib/libunwind/src/ia64/ucontext_i.h deleted file mode 100644 index ea32c8aaa09..00000000000 --- a/contrib/libunwind/src/ia64/ucontext_i.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (C) 2002 Hewlett-Packard Co. - Contributed by David Mosberger-Tang . - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Constants shared between setcontext() and getcontext(). Don't - install this header file. */ - -#define SIG_BLOCK 0 -#define SIG_UNBLOCK 1 -#define SIG_SETMASK 2 - -#define IA64_SC_FLAG_SYNCHRONOUS_BIT 63 - -#define SC_FLAGS 0x000 -#define SC_NAT 0x008 -#define SC_BSP 0x048 -#define SC_RNAT 0x050 -#define SC_UNAT 0x060 -#define SC_FPSR 0x068 -#define SC_PFS 0x070 -#define SC_LC 0x078 -#define SC_PR 0x080 -#define SC_BR 0x088 -#define SC_GR 0x0c8 -#define SC_FR 0x1d0 -#define SC_MASK 0x9d0 - - -#define rTMP r10 -#define rPOS r11 -#define rCPOS r14 -#define rNAT r15 -#define rFLAGS r16 - -#define rB5 r18 -#define rB4 r19 -#define rB3 r20 -#define rB2 r21 -#define rB1 r22 -#define rB0 r23 -#define rRSC r24 -#define rBSP r25 -#define rRNAT r26 -#define rUNAT r27 -#define rFPSR r28 -#define rPFS r29 -#define rLC r30 -#define rPR r31 diff --git a/contrib/libunwind/src/ia64/unwind_decoder.h b/contrib/libunwind/src/ia64/unwind_decoder.h deleted file mode 100644 index 7fd41740de8..00000000000 --- a/contrib/libunwind/src/ia64/unwind_decoder.h +++ /dev/null @@ -1,477 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* - * Generic IA-64 unwind info decoder. - * - * This file is used both by the Linux kernel and objdump. Please keep - * the two copies of this file in sync. - * - * You need to customize the decoder by defining the following - * macros/constants before including this file: - * - * Types: - * unw_word Unsigned integer type with at least 64 bits - * - * Register names: - * UNW_REG_BSP - * UNW_REG_BSPSTORE - * UNW_REG_FPSR - * UNW_REG_LC - * UNW_REG_PFS - * UNW_REG_PR - * UNW_REG_RNAT - * UNW_REG_PSP - * UNW_REG_RP - * UNW_REG_UNAT - * - * Decoder action macros: - * UNW_DEC_BAD_CODE(code) - * UNW_DEC_ABI(fmt,abi,context,arg) - * UNW_DEC_BR_GR(fmt,brmask,gr,arg) - * UNW_DEC_BR_MEM(fmt,brmask,arg) - * UNW_DEC_COPY_STATE(fmt,label,arg) - * UNW_DEC_EPILOGUE(fmt,t,ecount,arg) - * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg) - * UNW_DEC_FR_MEM(fmt,frmask,arg) - * UNW_DEC_GR_GR(fmt,grmask,gr,arg) - * UNW_DEC_GR_MEM(fmt,grmask,arg) - * UNW_DEC_LABEL_STATE(fmt,label,arg) - * UNW_DEC_MEM_STACK_F(fmt,t,size,arg) - * UNW_DEC_MEM_STACK_V(fmt,t,arg) - * UNW_DEC_PRIUNAT_GR(fmt,r,arg) - * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) - * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) - * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg) - * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg) - * UNW_DEC_PROLOGUE(fmt,body,rlen,arg) - * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg) - * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg) - * UNW_DEC_REG_REG(fmt,src,dst,arg) - * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg) - * UNW_DEC_REG_WHEN(fmt,reg,t,arg) - * UNW_DEC_RESTORE(fmt,t,abreg,arg) - * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg) - * UNW_DEC_SPILL_BASE(fmt,pspoff,arg) - * UNW_DEC_SPILL_MASK(fmt,imaskp,arg) - * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg) - * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg) - * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg) - * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg) - * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg) - * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg) - */ - -static unw_word -unw_decode_uleb128 (unsigned char **dpp) -{ - unsigned shift = 0; - unw_word byte, result = 0; - unsigned char *bp = *dpp; - - while (1) - { - byte = *bp++; - result |= (byte & 0x7f) << shift; - if ((byte & 0x80) == 0) - break; - shift += 7; - } - *dpp = bp; - return result; -} - -static unsigned char * -unw_decode_x1 (unsigned char *dp, unsigned char code, void *arg) -{ - unsigned char byte1, abreg; - unw_word t, off; - - byte1 = *dp++; - t = unw_decode_uleb128 (&dp); - off = unw_decode_uleb128 (&dp); - abreg = (byte1 & 0x7f); - if (byte1 & 0x80) - UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg); - else - UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg); - return dp; -} - -static unsigned char * -unw_decode_x2 (unsigned char *dp, unsigned char code, void *arg) -{ - unsigned char byte1, byte2, abreg, x, ytreg; - unw_word t; - - byte1 = *dp++; byte2 = *dp++; - t = unw_decode_uleb128 (&dp); - abreg = (byte1 & 0x7f); - ytreg = byte2; - x = (byte1 >> 7) & 1; - if ((byte1 & 0x80) == 0 && ytreg == 0) - UNW_DEC_RESTORE(X2, t, abreg, arg); - else - UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg); - return dp; -} - -static unsigned char * -unw_decode_x3 (unsigned char *dp, unsigned char code, void *arg) -{ - unsigned char byte1, byte2, abreg, qp; - unw_word t, off; - - byte1 = *dp++; byte2 = *dp++; - t = unw_decode_uleb128 (&dp); - off = unw_decode_uleb128 (&dp); - - qp = (byte1 & 0x3f); - abreg = (byte2 & 0x7f); - - if (byte1 & 0x80) - UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg); - else - UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg); - return dp; -} - -static unsigned char * -unw_decode_x4 (unsigned char *dp, unsigned char code, void *arg) -{ - unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg; - unw_word t; - - byte1 = *dp++; byte2 = *dp++; byte3 = *dp++; - t = unw_decode_uleb128 (&dp); - - qp = (byte1 & 0x3f); - abreg = (byte2 & 0x7f); - x = (byte2 >> 7) & 1; - ytreg = byte3; - - if ((byte2 & 0x80) == 0 && byte3 == 0) - UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg); - else - UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg); - return dp; -} - -static inline unsigned char * -unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg) -{ - int body = (code & 0x20) != 0; - unw_word rlen; - - rlen = (code & 0x1f); - UNW_DEC_PROLOGUE(R1, body, rlen, arg); - return dp; -} - -static inline unsigned char * -unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg) -{ - unsigned char byte1, mask, grsave; - unw_word rlen; - - byte1 = *dp++; - - mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); - grsave = (byte1 & 0x7f); - rlen = unw_decode_uleb128 (&dp); - UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg); - return dp; -} - -static inline unsigned char * -unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg) -{ - unw_word rlen; - - rlen = unw_decode_uleb128 (&dp); - UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg); - return dp; -} - -static inline unsigned char * -unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg) -{ - unsigned char brmask = (code & 0x1f); - - UNW_DEC_BR_MEM(P1, brmask, arg); - return dp; -} - -static inline unsigned char * -unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg) -{ - if ((code & 0x10) == 0) - { - unsigned char byte1 = *dp++; - - UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1), - (byte1 & 0x7f), arg); - } - else if ((code & 0x08) == 0) - { - unsigned char byte1 = *dp++, r, dst; - - r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); - dst = (byte1 & 0x7f); - switch (r) - { - case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break; - case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break; - case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break; - case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break; - case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break; - case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break; - case 6: UNW_DEC_RP_BR(P3, dst, arg); break; - case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break; - case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break; - case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break; - case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break; - case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break; - default: UNW_DEC_BAD_CODE(r); break; - } - } - else if ((code & 0x7) == 0) - UNW_DEC_SPILL_MASK(P4, dp, arg); - else if ((code & 0x7) == 1) - { - unw_word grmask, frmask, byte1, byte2, byte3; - - byte1 = *dp++; byte2 = *dp++; byte3 = *dp++; - grmask = ((byte1 >> 4) & 0xf); - frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3; - UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg); - } - else - UNW_DEC_BAD_CODE(code); - return dp; -} - -static inline unsigned char * -unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg) -{ - int gregs = (code & 0x10) != 0; - unsigned char mask = (code & 0x0f); - - if (gregs) - UNW_DEC_GR_MEM(P6, mask, arg); - else - UNW_DEC_FR_MEM(P6, mask, arg); - return dp; -} - -static inline unsigned char * -unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg) -{ - unsigned char r, byte1, byte2; - unw_word t, size; - - if ((code & 0x10) == 0) - { - r = (code & 0xf); - t = unw_decode_uleb128 (&dp); - switch (r) - { - case 0: - size = unw_decode_uleb128 (&dp); - UNW_DEC_MEM_STACK_F(P7, t, size, arg); - break; - - case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break; - case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break; - case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break; - case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break; - case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break; - case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break; - case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break; - case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break; - case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break; - case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break; - case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break; - case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break; - case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break; - case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break; - case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break; - default: UNW_DEC_BAD_CODE(r); break; - } - } - else - { - switch (code & 0xf) - { - case 0x0: /* p8 */ - { - r = *dp++; - t = unw_decode_uleb128 (&dp); - switch (r) - { - case 1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break; - case 2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break; - case 3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break; - case 4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break; - case 5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break; - case 6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break; - case 7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break; - case 8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break; - case 9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break; - case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break; - case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break; - case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break; - case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break; - case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break; - case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break; - case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break; - case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break; - case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break; - case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break; - default: UNW_DEC_BAD_CODE(r); break; - } - } - break; - - case 0x1: - byte1 = *dp++; byte2 = *dp++; - UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg); - break; - - case 0xf: /* p10 */ - byte1 = *dp++; byte2 = *dp++; - UNW_DEC_ABI(P10, byte1, byte2, arg); - break; - - case 0x9: - return unw_decode_x1 (dp, code, arg); - - case 0xa: - return unw_decode_x2 (dp, code, arg); - - case 0xb: - return unw_decode_x3 (dp, code, arg); - - case 0xc: - return unw_decode_x4 (dp, code, arg); - - default: - UNW_DEC_BAD_CODE(code); - break; - } - } - return dp; -} - -static inline unsigned char * -unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg) -{ - unw_word label = (code & 0x1f); - - if ((code & 0x20) != 0) - UNW_DEC_COPY_STATE(B1, label, arg); - else - UNW_DEC_LABEL_STATE(B1, label, arg); - return dp; -} - -static inline unsigned char * -unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg) -{ - unw_word t; - - t = unw_decode_uleb128 (&dp); - UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg); - return dp; -} - -static inline unsigned char * -unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg) -{ - unw_word t, ecount, label; - - if ((code & 0x10) == 0) - { - t = unw_decode_uleb128 (&dp); - ecount = unw_decode_uleb128 (&dp); - UNW_DEC_EPILOGUE(B3, t, ecount, arg); - } - else if ((code & 0x07) == 0) - { - label = unw_decode_uleb128 (&dp); - if ((code & 0x08) != 0) - UNW_DEC_COPY_STATE(B4, label, arg); - else - UNW_DEC_LABEL_STATE(B4, label, arg); - } - else - switch (code & 0x7) - { - case 1: return unw_decode_x1 (dp, code, arg); - case 2: return unw_decode_x2 (dp, code, arg); - case 3: return unw_decode_x3 (dp, code, arg); - case 4: return unw_decode_x4 (dp, code, arg); - default: UNW_DEC_BAD_CODE(code); break; - } - return dp; -} - -typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *); - -/* - * Decode one descriptor and return address of next descriptor. - */ -static inline unsigned char * -unw_decode (unsigned char *dp, int inside_body, void *arg) -{ - unsigned char code, primary; - - code = *dp++; - primary = code >> 5; - - if (primary < 2) - dp = unw_decode_r1 (dp, code, arg); - else if (primary == 2) - dp = unw_decode_r2 (dp, code, arg); - else if (primary == 3) - dp = unw_decode_r3 (dp, code, arg); - else if (inside_body) - switch (primary) - { - case 4: - case 5: dp = unw_decode_b1 (dp, code, arg); break; - case 6: dp = unw_decode_b2 (dp, code, arg); break; - case 7: dp = unw_decode_b3_x4 (dp, code, arg); break; - } - else - switch (primary) - { - case 4: dp = unw_decode_p1 (dp, code, arg); break; - case 5: dp = unw_decode_p2_p5 (dp, code, arg); break; - case 6: dp = unw_decode_p6 (dp, code, arg); break; - case 7: dp = unw_decode_p7_p10 (dp, code, arg); break; - } - return dp; -} diff --git a/contrib/libunwind/src/ia64/unwind_i.h b/contrib/libunwind/src/ia64/unwind_i.h deleted file mode 100644 index 8ccbb46c930..00000000000 --- a/contrib/libunwind/src/ia64/unwind_i.h +++ /dev/null @@ -1,633 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include -#include - -#include - -#include "rse.h" - -#include "libunwind_i.h" - -#define IA64_UNW_VER(x) ((x) >> 48) -#define IA64_UNW_FLAG_MASK ((unw_word_t) 0x0000ffff00000000ULL) -#define IA64_UNW_FLAG_OSMASK ((unw_word_t) 0x0000f00000000000ULL) -#define IA64_UNW_FLAG_EHANDLER(x) ((x) & (unw_word_t) 0x0000000100000000ULL) -#define IA64_UNW_FLAG_UHANDLER(x) ((x) & (unw_word_t) 0x0000000200000000ULL) -#define IA64_UNW_LENGTH(x) ((x) & (unw_word_t) 0x00000000ffffffffULL) - -#ifdef MIN -# undef MIN -#endif -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -#if !defined(HAVE_SYS_UC_ACCESS_H) && !defined(UNW_REMOTE_ONLY) - -static ALWAYS_INLINE void * -inlined_uc_addr (ucontext_t *uc, int reg, uint8_t *nat_bitnr) -{ - unw_word_t reg_addr; - void *addr; - - switch (reg) - { - case UNW_IA64_GR + 0: addr = &unw.read_only.r0; break; - case UNW_IA64_NAT + 0: addr = &unw.read_only.r0; break; - case UNW_IA64_FR + 0: addr = &unw.read_only.f0; break; - case UNW_IA64_FR + 1: - if (__BYTE_ORDER == __BIG_ENDIAN) - addr = &unw.read_only.f1_be; - else - addr = &unw.read_only.f1_le; - break; - case UNW_IA64_IP: addr = &uc->uc_mcontext.sc_br[0]; break; - case UNW_IA64_CFM: addr = &uc->uc_mcontext.sc_ar_pfs; break; - case UNW_IA64_AR_RNAT: addr = &uc->uc_mcontext.sc_ar_rnat; break; - case UNW_IA64_AR_UNAT: addr = &uc->uc_mcontext.sc_ar_unat; break; - case UNW_IA64_AR_LC: addr = &uc->uc_mcontext.sc_ar_lc; break; - case UNW_IA64_AR_FPSR: addr = &uc->uc_mcontext.sc_ar_fpsr; break; - case UNW_IA64_PR: addr = &uc->uc_mcontext.sc_pr; break; - case UNW_IA64_AR_BSPSTORE: addr = &uc->uc_mcontext.sc_ar_bsp; break; - - case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7: - case UNW_IA64_GR + 12: - addr = &uc->uc_mcontext.sc_gr[reg - UNW_IA64_GR]; - break; - - case UNW_IA64_NAT + 4 ... UNW_IA64_NAT + 7: - case UNW_IA64_NAT + 12: - addr = &uc->uc_mcontext.sc_nat; - reg_addr = (unw_word_t) &uc->uc_mcontext.sc_gr[reg - UNW_IA64_NAT]; - *nat_bitnr = reg - UNW_IA64_NAT; - break; - - case UNW_IA64_BR + 1 ... UNW_IA64_BR + 5: - addr = &uc->uc_mcontext.sc_br[reg - UNW_IA64_BR]; - break; - - case UNW_IA64_FR+ 2 ... UNW_IA64_FR+ 5: - case UNW_IA64_FR+16 ... UNW_IA64_FR+31: - addr = &uc->uc_mcontext.sc_fr[reg - UNW_IA64_FR]; - break; - - default: - addr = NULL; - } - return addr; -} - -static inline void * -uc_addr (ucontext_t *uc, int reg, uint8_t *nat_bitnr) -{ - if (__builtin_constant_p (reg)) - return inlined_uc_addr (uc, reg, nat_bitnr); - else - return tdep_uc_addr (uc, reg, nat_bitnr); -} - -/* Return TRUE if ADDR points inside unw.read_only_reg. */ - -static inline long -ia64_read_only_reg (void *addr) -{ - return ((unsigned long) ((char *) addr - (char *) &unw.read_only) - < sizeof (unw.read_only)); -} - -#endif /* !defined(HAVE_SYS_UC_ACCESS_H) && !defined(UNW_REMOTE_ONLY) */ - -/* Bits 0 and 1 of a location are used to encode its type: - bit 0: set if location uses floating-point format. - bit 1: set if location is a NaT bit on memory stack. */ - -#define IA64_LOC_TYPE_FP (1 << 0) -#define IA64_LOC_TYPE_MEMSTK_NAT (1 << 1) - -#ifdef UNW_LOCAL_ONLY -#define IA64_LOC_REG(r,t) (((r) << 2) | (t)) -#define IA64_LOC_ADDR(a,t) (((a) & ~0x3) | (t)) -#define IA64_LOC_UC_ADDR(a,t) IA64_LOC_ADDR(a, t) -#define IA64_NULL_LOC (0) - -#define IA64_GET_REG(l) ((l) >> 2) -#define IA64_GET_ADDR(l) ((l) & ~0x3) -#define IA64_IS_NULL_LOC(l) ((l) == 0) -#define IA64_IS_FP_LOC(l) (((l) & IA64_LOC_TYPE_FP) != 0) -#define IA64_IS_MEMSTK_NAT(l) (((l) & IA64_LOC_TYPE_MEMSTK_NAT) != 0) -#define IA64_IS_REG_LOC(l) 0 -#define IA64_IS_UC_LOC(l) 0 - -#define IA64_REG_LOC(c,r) ((unw_word_t) uc_addr((c)->as_arg, r, NULL)) -#define IA64_REG_NAT_LOC(c,r,n) ((unw_word_t) uc_addr((c)->as_arg, r, n)) -#define IA64_FPREG_LOC(c,r) \ - ((unw_word_t) uc_addr((c)->as_arg, (r), NULL) | IA64_LOC_TYPE_FP) - -# define ia64_find_proc_info(c,ip,n) \ - tdep_find_proc_info(unw_local_addr_space, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define ia64_put_unwind_info(c, pi) do { ; } while (0) - -/* Note: the register accessors (ia64_{get,set}{,fp}()) must check for - NULL locations because uc_addr() returns NULL for unsaved - registers. */ - -static inline int -ia64_getfp (struct cursor *c, unw_word_t loc, unw_fpreg_t *val) -{ - if (IA64_IS_NULL_LOC (loc)) - { - Debug (16, "access to unsaved register\n"); - return -UNW_EBADREG; - } - *val = *(unw_fpreg_t *) IA64_GET_ADDR (loc); - return 0; -} - -static inline int -ia64_putfp (struct cursor *c, unw_word_t loc, unw_fpreg_t val) -{ - unw_fpreg_t *addr = (unw_fpreg_t *) IA64_GET_ADDR (loc); - - if (IA64_IS_NULL_LOC (loc)) - { - Debug (16, "access to unsaved register\n"); - return -UNW_EBADREG; - } - else if (ia64_read_only_reg (addr)) - { - Debug (16, "attempt to read-only register\n"); - return -UNW_EREADONLYREG; - } - *addr = val; - return 0; -} - -static inline int -ia64_get (struct cursor *c, unw_word_t loc, unw_word_t *val) -{ - if (IA64_IS_NULL_LOC (loc)) - { - Debug (16, "access to unsaved register\n"); - return -UNW_EBADREG; - } - *val = *(unw_word_t *) IA64_GET_ADDR (loc); - return 0; -} - -static inline int -ia64_put (struct cursor *c, unw_word_t loc, unw_word_t val) -{ - unw_word_t *addr = (unw_word_t *) IA64_GET_ADDR (loc); - - if (IA64_IS_NULL_LOC (loc)) - { - Debug (16, "access to unsaved register\n"); - return -UNW_EBADREG; - } - else if (ia64_read_only_reg (addr)) - { - Debug (16, "attempt to read-only register\n"); - return -UNW_EREADONLYREG; - } - *addr = val; - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ - -/* Bits 0 and 1 of the second word (w1) of a location are used - to further distinguish what location we're dealing with: - - bit 0: set if the location is a register - bit 1: set of the location is accessed via uc_access(3) */ -#define IA64_LOC_TYPE_REG (1 << 0) -#define IA64_LOC_TYPE_UC (1 << 1) - -#define IA64_LOC_REG(r,t) ((ia64_loc_t) { ((r) << 2) | (t), \ - IA64_LOC_TYPE_REG }) -#define IA64_LOC_ADDR(a,t) ((ia64_loc_t) { ((a) & ~0x3) | (t), 0 }) -#define IA64_LOC_UC_ADDR(a,t) ((ia64_loc_t) { ((a) & ~0x3) | (t), \ - IA64_LOC_TYPE_UC }) -#define IA64_LOC_UC_REG(r,a) ((ia64_loc_t) { ((r) << 2), \ - ((a) | IA64_LOC_TYPE_REG \ - | IA64_LOC_TYPE_UC) }) -#define IA64_NULL_LOC ((ia64_loc_t) { 0, 0 }) - -#define IA64_GET_REG(l) ((l).w0 >> 2) -#define IA64_GET_ADDR(l) ((l).w0 & ~0x3) -#define IA64_GET_AUX_ADDR(l) ((l).w1 & ~0x3) -#define IA64_IS_NULL_LOC(l) (((l).w0 | (l).w1) == 0) -#define IA64_IS_FP_LOC(l) (((l).w0 & IA64_LOC_TYPE_FP) != 0) -#define IA64_IS_MEMSTK_NAT(l) (((l).w0 & IA64_LOC_TYPE_MEMSTK_NAT) != 0) -#define IA64_IS_REG_LOC(l) (((l).w1 & IA64_LOC_TYPE_REG) != 0) -#define IA64_IS_UC_LOC(l) (((l).w1 & IA64_LOC_TYPE_UC) != 0) - -#define IA64_REG_LOC(c,r) IA64_LOC_REG ((r), 0) -#define IA64_REG_NAT_LOC(c,r,n) IA64_LOC_REG ((r), 0) -#define IA64_FPREG_LOC(c,r) IA64_LOC_REG ((r), IA64_LOC_TYPE_FP) - -# define ia64_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define ia64_put_unwind_info(c,pi) \ - (*(c)->as->acc.put_unwind_info)((c)->as, (pi), (c)->as_arg) - -#define ia64_uc_access_reg UNW_OBJ(uc_access_reg) -#define ia64_uc_access_fpreg UNW_OBJ(uc_access_fpreg) - -extern int ia64_uc_access_reg (struct cursor *c, ia64_loc_t loc, - unw_word_t *valp, int write); -extern int ia64_uc_access_fpreg (struct cursor *c, ia64_loc_t loc, - unw_fpreg_t *valp, int write); - -static inline int -ia64_getfp (struct cursor *c, ia64_loc_t loc, unw_fpreg_t *val) -{ - unw_word_t addr; - int ret; - - if (IA64_IS_NULL_LOC (loc)) - { - Debug (16, "access to unsaved register\n"); - return -UNW_EBADREG; - } - - if (IA64_IS_UC_LOC (loc)) - return ia64_uc_access_fpreg (c, loc, val, 0); - - if (IA64_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, IA64_GET_REG (loc), - val, 0, c->as_arg); - - addr = IA64_GET_ADDR (loc); - ret = (*c->as->acc.access_mem) (c->as, addr + 0, &val->raw.bits[0], 0, - c->as_arg); - if (ret < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 8, &val->raw.bits[1], 0, - c->as_arg); -} - -static inline int -ia64_putfp (struct cursor *c, ia64_loc_t loc, unw_fpreg_t val) -{ - unw_word_t addr; - int ret; - - if (IA64_IS_NULL_LOC (loc)) - { - Debug (16, "access to unsaved register\n"); - return -UNW_EBADREG; - } - - if (IA64_IS_UC_LOC (loc)) - return ia64_uc_access_fpreg (c, loc, &val, 1); - - if (IA64_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, IA64_GET_REG (loc), &val, 1, - c->as_arg); - - addr = IA64_GET_ADDR (loc); - ret = (*c->as->acc.access_mem) (c->as, addr + 0, &val.raw.bits[0], 1, - c->as_arg); - if (ret < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 8, &val.raw.bits[1], 1, - c->as_arg); -} - -/* Get the 64 data bits from location LOC. If bit 0 is cleared, LOC - is a memory address, otherwise it is a register number. If the - register is a floating-point register, the 64 bits are read from - the significand bits. */ - -static inline int -ia64_get (struct cursor *c, ia64_loc_t loc, unw_word_t *val) -{ - if (IA64_IS_NULL_LOC (loc)) - { - Debug (16, "access to unsaved register\n"); - return -UNW_EBADREG; - } - - if (IA64_IS_FP_LOC (loc)) - { - unw_fpreg_t tmp; - int ret; - - ret = ia64_getfp (c, loc, &tmp); - if (ret < 0) - return ret; - - if (c->as->big_endian) - *val = tmp.raw.bits[1]; - else - *val = tmp.raw.bits[0]; - return 0; - } - - if (IA64_IS_UC_LOC (loc)) - return ia64_uc_access_reg (c, loc, val, 0); - - if (IA64_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg)(c->as, IA64_GET_REG (loc), val, 0, - c->as_arg); - else - return (*c->as->acc.access_mem)(c->as, IA64_GET_ADDR (loc), val, 0, - c->as_arg); -} - -static inline int -ia64_put (struct cursor *c, ia64_loc_t loc, unw_word_t val) -{ - if (IA64_IS_NULL_LOC (loc)) - { - Debug (16, "access to unsaved register\n"); - return -UNW_EBADREG; - } - - if (IA64_IS_FP_LOC (loc)) - { - unw_fpreg_t tmp; - - memset (&tmp, 0, sizeof (tmp)); - if (c->as->big_endian) - tmp.raw.bits[1] = val; - else - tmp.raw.bits[0] = val; - return ia64_putfp (c, loc, tmp); - } - - if (IA64_IS_UC_LOC (loc)) - return ia64_uc_access_reg (c, loc, &val, 1); - - if (IA64_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg)(c->as, IA64_GET_REG (loc), &val, 1, - c->as_arg); - else - return (*c->as->acc.access_mem)(c->as, IA64_GET_ADDR (loc), &val, 1, - c->as_arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - -struct ia64_unwind_block - { - unw_word_t header; - unw_word_t desc[0]; /* unwind descriptors */ - - /* Personality routine and language-specific data follow behind - descriptors. */ - }; - -enum ia64_where - { - IA64_WHERE_NONE, /* register isn't saved at all */ - IA64_WHERE_GR, /* register is saved in a general register */ - IA64_WHERE_FR, /* register is saved in a floating-point register */ - IA64_WHERE_BR, /* register is saved in a branch register */ - IA64_WHERE_SPREL, /* register is saved on memstack (sp-relative) */ - IA64_WHERE_PSPREL, /* register is saved on memstack (psp-relative) */ - - /* At the end of each prologue these locations get resolved to - IA64_WHERE_PSPREL and IA64_WHERE_GR, respectively: */ - - IA64_WHERE_SPILL_HOME, /* register is saved in its spill home */ - IA64_WHERE_GR_SAVE /* register is saved in next general register */ - }; - -#define IA64_WHEN_NEVER 0x7fffffff - -struct ia64_reg_info - { - unw_word_t val; /* save location: register number or offset */ - enum ia64_where where; /* where the register gets saved */ - int when; /* when the register gets saved */ - }; - -struct ia64_labeled_state; /* opaque structure */ - -struct ia64_reg_state - { - struct ia64_reg_state *next; /* next (outer) element on state stack */ - struct ia64_reg_info reg[IA64_NUM_PREGS]; /* register save locations */ - }; - -struct ia64_state_record - { - unsigned int first_region : 1; /* is this the first region? */ - unsigned int done : 1; /* are we done scanning descriptors? */ - unsigned int any_spills : 1; /* got any register spills? */ - unsigned int in_body : 1; /* are we inside prologue or body? */ - uint8_t *imask; /* imask of spill_mask record or NULL */ - uint16_t abi_marker; - - unw_word_t pr_val; /* predicate values */ - unw_word_t pr_mask; /* predicate mask */ - - long spill_offset; /* psp-relative offset for spill base */ - int region_start; - int region_len; - int when_sp_restored; - int epilogue_count; - int when_target; - - uint8_t gr_save_loc; /* next save register */ - uint8_t return_link_reg; /* branch register used as return pointer */ - - struct ia64_labeled_state *labeled_states; - struct ia64_reg_state curr; - }; - -struct ia64_labeled_state - { - struct ia64_labeled_state *next; /* next label (or NULL) */ - unsigned long label; /* label for this state */ - struct ia64_reg_state saved_state; - }; - -/* Convenience macros: */ -#define ia64_make_proc_info UNW_OBJ(make_proc_info) -#define ia64_fetch_proc_info UNW_OBJ(fetch_proc_info) -#define ia64_create_state_record UNW_OBJ(create_state_record) -#define ia64_free_state_record UNW_OBJ(free_state_record) -#define ia64_find_save_locs UNW_OBJ(find_save_locs) -#define ia64_validate_cache UNW_OBJ(ia64_validate_cache) -#define ia64_local_validate_cache UNW_OBJ(ia64_local_validate_cache) -#define ia64_per_thread_cache UNW_OBJ(per_thread_cache) -#define ia64_scratch_loc UNW_OBJ(scratch_loc) -#define ia64_local_resume UNW_OBJ(local_resume) -#define ia64_local_addr_space_init UNW_OBJ(local_addr_space_init) -#define ia64_strloc UNW_OBJ(strloc) -#define ia64_install_cursor UNW_OBJ(install_cursor) -#define rbs_switch UNW_OBJ(rbs_switch) -#define rbs_find_stacked UNW_OBJ(rbs_find_stacked) - -extern int ia64_make_proc_info (struct cursor *c); -extern int ia64_fetch_proc_info (struct cursor *c, unw_word_t ip, - int need_unwind_info); -/* The proc-info must be valid for IP before this routine can be - called: */ -extern int ia64_create_state_record (struct cursor *c, - struct ia64_state_record *sr); -extern int ia64_free_state_record (struct ia64_state_record *sr); -extern int ia64_find_save_locs (struct cursor *c); -extern void ia64_validate_cache (unw_addr_space_t as, void *arg); -extern int ia64_local_validate_cache (unw_addr_space_t as, void *arg); -extern void ia64_local_addr_space_init (void); -extern ia64_loc_t ia64_scratch_loc (struct cursor *c, unw_regnum_t reg, - uint8_t *nat_bitnr); - -extern NORETURN void ia64_install_cursor (struct cursor *c, - unw_word_t pri_unat, - unw_word_t *extra, - unw_word_t bspstore, - unw_word_t dirty_size, - unw_word_t *dirty_partition, - unw_word_t dirty_rnat); -extern int ia64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, - void *arg); -extern int rbs_switch (struct cursor *c, - unw_word_t saved_bsp, unw_word_t saved_bspstore, - ia64_loc_t saved_rnat_loc); -extern int rbs_find_stacked (struct cursor *c, unw_word_t regs_to_skip, - ia64_loc_t *locp, ia64_loc_t *rnat_locp); - -#ifndef UNW_REMOTE_ONLY -# define NEED_RBS_COVER_AND_FLUSH -# define rbs_cover_and_flush UNW_OBJ(rbs_cover_and_flush) - extern int rbs_cover_and_flush (struct cursor *c, unw_word_t nregs, - unw_word_t *dirty_partition, - unw_word_t *dirty_rnat, - unw_word_t *bspstore); -#endif - -/* Warning: ia64_strloc() is for debugging only and it is NOT re-entrant! */ -extern const char *ia64_strloc (ia64_loc_t loc); - -/* Return true if the register-backing store is inside a ucontext_t - that needs to be accessed via uc_access(3). */ - -static inline int -rbs_on_uc (struct rbs_area *rbs) -{ - return IA64_IS_UC_LOC (rbs->rnat_loc) && !IA64_IS_REG_LOC (rbs->rnat_loc); -} - -/* Return true if BSP points to a word that's stored on register - backing-store RBS. */ -static inline int -rbs_contains (struct rbs_area *rbs, unw_word_t bsp) -{ - int result; - - /* Caveat: this takes advantage of unsigned arithmetic. The full - test is (bsp >= rbs->end - rbs->size) && (bsp < rbs->end). We - take advantage of the fact that -n == ~n + 1. */ - result = bsp - rbs->end > ~rbs->size; - Debug (16, "0x%lx in [0x%lx-0x%lx) => %d\n", - (long) bsp, (long) (rbs->end - rbs->size), (long) rbs->end, result); - return result; -} - -static inline ia64_loc_t -rbs_get_rnat_loc (struct rbs_area *rbs, unw_word_t bsp) -{ - unw_word_t rnat_addr = rse_rnat_addr (bsp); - ia64_loc_t rnat_loc; - - if (rbs_contains (rbs, rnat_addr)) - { - if (rbs_on_uc (rbs)) - rnat_loc = IA64_LOC_UC_ADDR (rnat_addr, 0); - else - rnat_loc = IA64_LOC_ADDR (rnat_addr, 0); - } - else - rnat_loc = rbs->rnat_loc; - return rnat_loc; -} - -static inline ia64_loc_t -rbs_loc (struct rbs_area *rbs, unw_word_t bsp) -{ - if (rbs_on_uc (rbs)) - return IA64_LOC_UC_ADDR (bsp, 0); - else - return IA64_LOC_ADDR (bsp, 0); -} - -static inline int -ia64_get_stacked (struct cursor *c, unw_word_t reg, - ia64_loc_t *locp, ia64_loc_t *rnat_locp) -{ - struct rbs_area *rbs = c->rbs_area + c->rbs_curr; - unw_word_t addr, regs_to_skip = reg - 32; - int ret = 0; - - assert (reg >= 32 && reg < 128); - - addr = rse_skip_regs (c->bsp, regs_to_skip); - if (locp) - *locp = rbs_loc (rbs, addr); - if (rnat_locp) - *rnat_locp = rbs_get_rnat_loc (rbs, addr); - - if (!rbs_contains (rbs, addr)) - ret = rbs_find_stacked (c, regs_to_skip, locp, rnat_locp); - return ret; -} - -/* The UNaT slot # calculation is identical to the one for RNaT slots, - but for readability/clarity, we don't want to use - ia64_rnat_slot_num() directly. */ -#define ia64_unat_slot_num(addr) rse_slot_num(addr) - -/* The following are helper macros which makes it easier for libunwind - to be used in the kernel. They allow the kernel to optimize away - any unused code without littering everything with #ifdefs. */ -#define ia64_is_big_endian(c) ((c)->as->big_endian) -#define ia64_get_abi(c) ((c)->as->abi) -#define ia64_set_abi(c, v) ((c)->as->abi = (v)) -#define ia64_get_abi_marker(c) ((c)->last_abi_marker) - -/* XXX should be in glibc: */ -#ifndef IA64_SC_FLAG_ONSTACK -# define IA64_SC_FLAG_ONSTACK_BIT 0 /* running on signal stack? */ -# define IA64_SC_FLAG_IN_SYSCALL_BIT 1 /* did signal interrupt a syscall? */ -# define IA64_SC_FLAG_FPH_VALID_BIT 2 /* is state in f[32]-f[127] valid? */ - -# define IA64_SC_FLAG_ONSTACK (1 << IA64_SC_FLAG_ONSTACK_BIT) -# define IA64_SC_FLAG_IN_SYSCALL (1 << IA64_SC_FLAG_IN_SYSCALL_BIT) -# define IA64_SC_FLAG_FPH_VALID (1 << IA64_SC_FLAG_FPH_VALID_BIT) -#endif - -#endif /* unwind_i_h */ diff --git a/contrib/libunwind/src/libunwind-generic.pc.in b/contrib/libunwind/src/libunwind-generic.pc.in deleted file mode 100644 index 1f3baffe5bd..00000000000 --- a/contrib/libunwind/src/libunwind-generic.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libunwind-generic -Description: libunwind generic library -Version: @VERSION@ -Requires: libunwind -Libs: -L${libdir} -lunwind-generic -Cflags: -I${includedir} diff --git a/contrib/libunwind/src/mi/Gdestroy_addr_space.c b/contrib/libunwind/src/mi/Gdestroy_addr_space.c deleted file mode 100644 index 719c051e38d..00000000000 --- a/contrib/libunwind/src/mi/Gdestroy_addr_space.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED void -unw_destroy_addr_space (unw_addr_space_t as) -{ -#ifndef UNW_LOCAL_ONLY -# if UNW_DEBUG - memset (as, 0, sizeof (*as)); -# endif - free (as); -#endif -} diff --git a/contrib/libunwind/src/mi/Gdyn-extract.c b/contrib/libunwind/src/mi/Gdyn-extract.c deleted file mode 100644 index 5f7682e650d..00000000000 --- a/contrib/libunwind/src/mi/Gdyn-extract.c +++ /dev/null @@ -1,64 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -HIDDEN int -unwi_extract_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, unw_dyn_info_t *di, - int need_unwind_info, void *arg) -{ - pi->start_ip = di->start_ip; - pi->end_ip = di->end_ip; - pi->gp = di->gp; - pi->format = di->format; - switch (di->format) - { - case UNW_INFO_FORMAT_DYNAMIC: - pi->handler = di->u.pi.handler; - pi->lsda = 0; - pi->flags = di->u.pi.flags; - pi->unwind_info_size = 0; - if (need_unwind_info) - pi->unwind_info = di; - else - pi->unwind_info = NULL; - return 0; - - case UNW_INFO_FORMAT_TABLE: - case UNW_INFO_FORMAT_REMOTE_TABLE: - case UNW_INFO_FORMAT_ARM_EXIDX: - case UNW_INFO_FORMAT_IP_OFFSET: -#ifdef tdep_search_unwind_table - /* call platform-specific search routine: */ - return tdep_search_unwind_table (as, ip, di, pi, need_unwind_info, arg); -#else - /* fall through */ -#endif - default: - break; - } - return -UNW_EINVAL; -} diff --git a/contrib/libunwind/src/mi/Gdyn-remote.c b/contrib/libunwind/src/mi/Gdyn-remote.c deleted file mode 100644 index 1f029b4deb9..00000000000 --- a/contrib/libunwind/src/mi/Gdyn-remote.c +++ /dev/null @@ -1,326 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "libunwind_i.h" -#include "remote.h" - -static void -free_regions (unw_dyn_region_info_t *region) -{ - if (region->next) - free_regions (region->next); - free (region); -} - -static int -intern_op (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, - unw_dyn_op_t *op, void *arg) -{ - int ret; - - if ((ret = fetch8 (as, a, addr, &op->tag, arg)) < 0 - || (ret = fetch8 (as, a, addr, &op->qp, arg)) < 0 - || (ret = fetch16 (as, a, addr, &op->reg, arg)) < 0 - || (ret = fetch32 (as, a, addr, &op->when, arg)) < 0 - || (ret = fetchw (as, a, addr, &op->val, arg)) < 0) - return ret; - return 0; -} - -static int -intern_regions (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, unw_dyn_region_info_t **regionp, void *arg) -{ - uint32_t insn_count, op_count, i; - unw_dyn_region_info_t *region; - unw_word_t next_addr; - int ret; - - *regionp = NULL; - - if (!*addr) - return 0; /* NULL region-list */ - - if ((ret = fetchw (as, a, addr, &next_addr, arg)) < 0 - || (ret = fetch32 (as, a, addr, (int32_t *) &insn_count, arg)) < 0 - || (ret = fetch32 (as, a, addr, (int32_t *) &op_count, arg)) < 0) - return ret; - - region = calloc (1, _U_dyn_region_info_size (op_count)); - if (!region) - { - ret = -UNW_ENOMEM; - goto out; - } - - region->insn_count = insn_count; - region->op_count = op_count; - for (i = 0; i < op_count; ++i) - if ((ret = intern_op (as, a, addr, region->op + i, arg)) < 0) - goto out; - - if (next_addr) - if ((ret = intern_regions (as, a, &next_addr, ®ion->next, arg)) < 0) - goto out; - - *regionp = region; - return 0; - - out: - if (region) - free_regions (region); - return ret; -} - -static int -intern_array (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, unw_word_t table_len, unw_word_t **table_data, - void *arg) -{ - unw_word_t i, *data = calloc (table_len, WSIZE); - int ret = 0; - - if (!data) - { - ret = -UNW_ENOMEM; - goto out; - } - - for (i = 0; i < table_len; ++i) - if (fetchw (as, a, addr, data + i, arg) < 0) - goto out; - - *table_data = data; - return 0; - - out: - if (data) - free (data); - return ret; -} - -static void -free_dyn_info (unw_dyn_info_t *di) -{ - switch (di->format) - { - case UNW_INFO_FORMAT_DYNAMIC: - if (di->u.pi.regions) - { - free_regions (di->u.pi.regions); - di->u.pi.regions = NULL; - } - break; - - case UNW_INFO_FORMAT_TABLE: - if (di->u.ti.table_data) - { - free (di->u.ti.table_data); - di->u.ti.table_data = NULL; - } - break; - - case UNW_INFO_FORMAT_REMOTE_TABLE: - default: - break; - } -} - -static int -intern_dyn_info (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t *addr, unw_dyn_info_t *di, void *arg) -{ - unw_word_t first_region; - int ret; - - switch (di->format) - { - case UNW_INFO_FORMAT_DYNAMIC: - if ((ret = fetchw (as, a, addr, &di->u.pi.name_ptr, arg)) < 0 - || (ret = fetchw (as, a, addr, &di->u.pi.handler, arg)) < 0 - || (ret = fetch32 (as, a, addr, - (int32_t *) &di->u.pi.flags, arg)) < 0) - goto out; - *addr += 4; /* skip over pad0 */ - if ((ret = fetchw (as, a, addr, &first_region, arg)) < 0 - || (ret = intern_regions (as, a, &first_region, &di->u.pi.regions, - arg)) < 0) - goto out; - break; - - case UNW_INFO_FORMAT_TABLE: - if ((ret = fetchw (as, a, addr, &di->u.ti.name_ptr, arg)) < 0 - || (ret = fetchw (as, a, addr, &di->u.ti.segbase, arg)) < 0 - || (ret = fetchw (as, a, addr, &di->u.ti.table_len, arg)) < 0 - || (ret = intern_array (as, a, addr, di->u.ti.table_len, - &di->u.ti.table_data, arg)) < 0) - goto out; - break; - - case UNW_INFO_FORMAT_REMOTE_TABLE: - if ((ret = fetchw (as, a, addr, &di->u.rti.name_ptr, arg)) < 0 - || (ret = fetchw (as, a, addr, &di->u.rti.segbase, arg)) < 0 - || (ret = fetchw (as, a, addr, &di->u.rti.table_len, arg)) < 0 - || (ret = fetchw (as, a, addr, &di->u.rti.table_data, arg)) < 0) - goto out; - break; - - default: - ret = -UNW_ENOINFO; - goto out; - } - return 0; - - out: - free_dyn_info (di); - return ret; -} - -HIDDEN int -unwi_dyn_remote_find_proc_info (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - unw_accessors_t *a = unw_get_accessors (as); - unw_word_t dyn_list_addr, addr, next_addr, gen1, gen2, start_ip, end_ip; - unw_dyn_info_t *di = NULL; - int ret; - - if (as->dyn_info_list_addr) - dyn_list_addr = as->dyn_info_list_addr; - else - { - if ((*a->get_dyn_info_list_addr) (as, &dyn_list_addr, arg) < 0) - return -UNW_ENOINFO; - if (as->caching_policy != UNW_CACHE_NONE) - as->dyn_info_list_addr = dyn_list_addr; - } - - do - { - addr = dyn_list_addr; - - ret = -UNW_ENOINFO; - - if (fetchw (as, a, &addr, &gen1, arg) < 0 - || fetchw (as, a, &addr, &next_addr, arg) < 0) - return ret; - - for (addr = next_addr; addr != 0; addr = next_addr) - { - if (fetchw (as, a, &addr, &next_addr, arg) < 0) - goto recheck; /* only fail if generation # didn't change */ - - addr += WSIZE; /* skip over prev_addr */ - - if (fetchw (as, a, &addr, &start_ip, arg) < 0 - || fetchw (as, a, &addr, &end_ip, arg) < 0) - goto recheck; /* only fail if generation # didn't change */ - - if (ip >= start_ip && ip < end_ip) - { - if (!di) - di = calloc (1, sizeof (*di)); - - di->start_ip = start_ip; - di->end_ip = end_ip; - - if (fetchw (as, a, &addr, &di->gp, arg) < 0 - || fetch32 (as, a, &addr, &di->format, arg) < 0) - goto recheck; /* only fail if generation # didn't change */ - - addr += 4; /* skip over padding */ - - if (need_unwind_info - && intern_dyn_info (as, a, &addr, di, arg) < 0) - goto recheck; /* only fail if generation # didn't change */ - - if (unwi_extract_dynamic_proc_info (as, ip, pi, di, - need_unwind_info, arg) < 0) - { - free_dyn_info (di); - goto recheck; /* only fail if generation # didn't change */ - } - ret = 0; /* OK, found it */ - break; - } - } - - /* Re-check generation number to ensure the data we have is - consistent. */ - recheck: - addr = dyn_list_addr; - if (fetchw (as, a, &addr, &gen2, arg) < 0) - return ret; - } - while (gen1 != gen2); - - if (ret < 0 && di) - free (di); - - return ret; -} - -HIDDEN void -unwi_dyn_remote_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, - void *arg) -{ - if (!pi->unwind_info) - return; - - free_dyn_info (pi->unwind_info); - free (pi->unwind_info); - pi->unwind_info = NULL; -} - -/* Returns 1 if the cache is up-to-date or -1 if the cache contained - stale data and had to be flushed. */ - -HIDDEN int -unwi_dyn_validate_cache (unw_addr_space_t as, void *arg) -{ - unw_word_t addr, gen; - unw_accessors_t *a; - - if (!as->dyn_info_list_addr) - /* If we don't have the dyn_info_list_addr, we don't have anything - in the cache. */ - return 0; - - a = unw_get_accessors (as); - addr = as->dyn_info_list_addr; - - if (fetchw (as, a, &addr, &gen, arg) < 0) - return 1; - - if (gen == as->dyn_generation) - return 1; - - unw_flush_cache (as, 0, 0); - as->dyn_generation = gen; - return -1; -} diff --git a/contrib/libunwind/src/mi/Gfind_dynamic_proc_info.c b/contrib/libunwind/src/mi/Gfind_dynamic_proc_info.c deleted file mode 100644 index 98d35012861..00000000000 --- a/contrib/libunwind/src/mi/Gfind_dynamic_proc_info.c +++ /dev/null @@ -1,91 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -static inline int -local_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - return -UNW_ENOINFO; -} - -#else /* !UNW_REMOTE_ONLY */ - -static inline int -local_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - unw_dyn_info_list_t *list; - unw_dyn_info_t *di; - -#ifndef UNW_LOCAL_ONLY -# pragma weak _U_dyn_info_list_addr - if (!_U_dyn_info_list_addr) - return -UNW_ENOINFO; -#endif - - list = (unw_dyn_info_list_t *) (uintptr_t) _U_dyn_info_list_addr (); - for (di = list->first; di; di = di->next) - if (ip >= di->start_ip && ip < di->end_ip) - return unwi_extract_dynamic_proc_info (as, ip, pi, di, need_unwind_info, - arg); - return -UNW_ENOINFO; -} - -#endif /* !UNW_REMOTE_ONLY */ - -#ifdef UNW_LOCAL_ONLY - -static inline int -remote_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - return -UNW_ENOINFO; -} - -#else /* !UNW_LOCAL_ONLY */ - -static inline int -remote_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - return unwi_dyn_remote_find_proc_info (as, ip, pi, need_unwind_info, arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - -HIDDEN int -unwi_find_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, int need_unwind_info, - void *arg) -{ - if (as == unw_local_addr_space) - return local_find_proc_info (as, ip, pi, need_unwind_info, arg); - else - return remote_find_proc_info (as, ip, pi, need_unwind_info, arg); -} diff --git a/contrib/libunwind/src/mi/Gget_accessors.c b/contrib/libunwind/src/mi/Gget_accessors.c deleted file mode 100644 index 548c7636d22..00000000000 --- a/contrib/libunwind/src/mi/Gget_accessors.c +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002, 2004-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED unw_accessors_t * -unw_get_accessors (unw_addr_space_t as) -{ - if (!tdep_init_done) - tdep_init (); - return &as->acc; -} diff --git a/contrib/libunwind/src/mi/Gget_fpreg.c b/contrib/libunwind/src/mi/Gget_fpreg.c deleted file mode 100644 index f2f7405ec5a..00000000000 --- a/contrib/libunwind/src/mi/Gget_fpreg.c +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_get_fpreg (unw_cursor_t *cursor, int regnum, unw_fpreg_t *valp) -{ - struct cursor *c = (struct cursor *) cursor; - - return tdep_access_fpreg (c, regnum, valp, 0); -} diff --git a/contrib/libunwind/src/mi/Gget_proc_info_by_ip.c b/contrib/libunwind/src/mi/Gget_proc_info_by_ip.c deleted file mode 100644 index c39312d5640..00000000000 --- a/contrib/libunwind/src/mi/Gget_proc_info_by_ip.c +++ /dev/null @@ -1,39 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_get_proc_info_by_ip (unw_addr_space_t as, unw_word_t ip, - unw_proc_info_t *pi, void *as_arg) -{ - unw_accessors_t *a = unw_get_accessors (as); - int ret; - - ret = unwi_find_dynamic_proc_info (as, ip, pi, 0, as_arg); - if (ret == -UNW_ENOINFO) - ret = (*a->find_proc_info) (as, ip, pi, 0, as_arg); - return ret; -} diff --git a/contrib/libunwind/src/mi/Gget_proc_name.c b/contrib/libunwind/src/mi/Gget_proc_name.c deleted file mode 100644 index 41ed9394da4..00000000000 --- a/contrib/libunwind/src/mi/Gget_proc_name.c +++ /dev/null @@ -1,118 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" -#include "remote.h" - -static inline int -intern_string (unw_addr_space_t as, unw_accessors_t *a, - unw_word_t addr, char *buf, size_t buf_len, void *arg) -{ - size_t i; - int ret; - - for (i = 0; i < buf_len; ++i) - { - if ((ret = fetch8 (as, a, &addr, (int8_t *) buf + i, arg)) < 0) - return ret; - - if (buf[i] == '\0') - return 0; /* copied full string; return success */ - } - buf[buf_len - 1] = '\0'; /* ensure string is NUL terminated */ - return -UNW_ENOMEM; -} - -static inline int -get_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, void *arg) -{ - unw_accessors_t *a = unw_get_accessors (as); - unw_proc_info_t pi; - int ret; - - buf[0] = '\0'; /* always return a valid string, even if it's empty */ - - ret = unwi_find_dynamic_proc_info (as, ip, &pi, 1, arg); - if (ret == 0) - { - unw_dyn_info_t *di = pi.unwind_info; - - if (offp) - *offp = ip - pi.start_ip; - - switch (di->format) - { - case UNW_INFO_FORMAT_DYNAMIC: - ret = intern_string (as, a, di->u.pi.name_ptr, buf, buf_len, arg); - break; - - case UNW_INFO_FORMAT_TABLE: - case UNW_INFO_FORMAT_REMOTE_TABLE: - /* XXX should we create a fake name, e.g.: "tablenameN", - where N is the index of the function in the table??? */ - ret = -UNW_ENOINFO; - break; - - default: - ret = -UNW_EINVAL; - break; - } - unwi_put_dynamic_unwind_info (as, &pi, arg); - return ret; - } - - if (ret != -UNW_ENOINFO) - return ret; - - /* not a dynamic procedure, try to lookup static procedure name: */ - - if (a->get_proc_name) - return (*a->get_proc_name) (as, ip, buf, buf_len, offp, arg); - - return -UNW_ENOINFO; -} - -PROTECTED int -unw_get_proc_name (unw_cursor_t *cursor, char *buf, size_t buf_len, - unw_word_t *offp) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t ip; - int error; - - ip = tdep_get_ip (c); -#if !defined(__ia64__) - if (c->dwarf.use_prev_instr) - --ip; -#endif - error = get_proc_name (tdep_get_as (c), ip, buf, buf_len, offp, - tdep_get_as_arg (c)); -#if !defined(__ia64__) - if (c->dwarf.use_prev_instr && offp != NULL && error == 0) - *offp += 1; -#endif - return error; -} diff --git a/contrib/libunwind/src/mi/Gget_reg.c b/contrib/libunwind/src/mi/Gget_reg.c deleted file mode 100644 index 7c0a5a9c06c..00000000000 --- a/contrib/libunwind/src/mi/Gget_reg.c +++ /dev/null @@ -1,41 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_get_reg (unw_cursor_t *cursor, int regnum, unw_word_t *valp) -{ - struct cursor *c = (struct cursor *) cursor; - - // We can get the IP value directly without needing a lookup. - if (regnum == UNW_REG_IP) - { - *valp = tdep_get_ip (c); - return 0; - } - - return tdep_access_reg (c, regnum, valp, 0); -} diff --git a/contrib/libunwind/src/mi/Gput_dynamic_unwind_info.c b/contrib/libunwind/src/mi/Gput_dynamic_unwind_info.c deleted file mode 100644 index ca377c98a8c..00000000000 --- a/contrib/libunwind/src/mi/Gput_dynamic_unwind_info.c +++ /dev/null @@ -1,55 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -HIDDEN void -unwi_put_dynamic_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, - void *arg) -{ - switch (pi->format) - { - case UNW_INFO_FORMAT_DYNAMIC: -#ifndef UNW_LOCAL_ONLY -# ifdef UNW_REMOTE_ONLY - unwi_dyn_remote_put_unwind_info (as, pi, arg); -# else - if (as != unw_local_addr_space) - unwi_dyn_remote_put_unwind_info (as, pi, arg); -# endif -#endif - break; - - case UNW_INFO_FORMAT_TABLE: - case UNW_INFO_FORMAT_REMOTE_TABLE: -#ifdef tdep_put_unwind_info - tdep_put_unwind_info (as, pi, arg); - break; -#endif - /* fall through */ - default: - break; - } -} diff --git a/contrib/libunwind/src/mi/Gset_cache_size.c b/contrib/libunwind/src/mi/Gset_cache_size.c deleted file mode 100644 index a0d8b5bf13c..00000000000 --- a/contrib/libunwind/src/mi/Gset_cache_size.c +++ /dev/null @@ -1,72 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2014 - Contributed by Milian Wolff - and Dave Watson - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_set_cache_size (unw_addr_space_t as, size_t size, int flag) -{ - size_t power = 1; - unsigned short log_size = 0; - - if (!tdep_init_done) - tdep_init (); - - if (flag != 0) - return -1; - - /* Currently not supported for per-thread cache due to memory leak */ - /* A pthread-key destructor would work, but is not signal safe */ -#if defined(HAVE___THREAD) && HAVE___THREAD - return -1; -#endif - - /* Round up to next power of two, slowly but portably */ - while(power < size) - { - power *= 2; - log_size++; - /* Largest size currently supported by rs_cache */ - if (log_size >= 15) - break; - } - -#if !defined(__ia64__) - if (log_size == as->global_cache.log_size) - return 0; /* no change */ - - as->global_cache.log_size = log_size; -#endif - - /* Ensure caches are empty (and initialized). */ - unw_flush_cache (as, 0, 0); -#ifdef __ia64__ - return 0; -#else - /* Synchronously purge cache, to ensure memory is allocated */ - return dwarf_flush_rs_cache(&as->global_cache); -#endif -} diff --git a/contrib/libunwind/src/mi/Gset_caching_policy.c b/contrib/libunwind/src/mi/Gset_caching_policy.c deleted file mode 100644 index 9df9eb82e5c..00000000000 --- a/contrib/libunwind/src/mi/Gset_caching_policy.c +++ /dev/null @@ -1,46 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_set_caching_policy (unw_addr_space_t as, unw_caching_policy_t policy) -{ - if (!tdep_init_done) - tdep_init (); - -#if !(defined(HAVE___THREAD) && HAVE___THREAD) - if (policy == UNW_CACHE_PER_THREAD) - policy = UNW_CACHE_GLOBAL; -#endif - - if (policy == as->caching_policy) - return 0; /* no change */ - - as->caching_policy = policy; - /* Ensure caches are empty (and initialized). */ - unw_flush_cache (as, 0, 0); - return 0; -} diff --git a/contrib/libunwind/src/mi/Gset_fpreg.c b/contrib/libunwind/src/mi/Gset_fpreg.c deleted file mode 100644 index 4f2fa7be6b9..00000000000 --- a/contrib/libunwind/src/mi/Gset_fpreg.c +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_set_fpreg (unw_cursor_t *cursor, int regnum, unw_fpreg_t val) -{ - struct cursor *c = (struct cursor *) cursor; - - return tdep_access_fpreg (c, regnum, &val, 1); -} diff --git a/contrib/libunwind/src/mi/Gset_reg.c b/contrib/libunwind/src/mi/Gset_reg.c deleted file mode 100644 index c9b6e6aa647..00000000000 --- a/contrib/libunwind/src/mi/Gset_reg.c +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_set_reg (unw_cursor_t *cursor, int regnum, unw_word_t valp) -{ - struct cursor *c = (struct cursor *) cursor; - - return tdep_access_reg (c, regnum, &valp, 1); -} diff --git a/contrib/libunwind/src/mi/Ldestroy_addr_space.c b/contrib/libunwind/src/mi/Ldestroy_addr_space.c deleted file mode 100644 index 5bf9364bc73..00000000000 --- a/contrib/libunwind/src/mi/Ldestroy_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gdestroy_addr_space.c" -#endif diff --git a/contrib/libunwind/src/mi/Ldyn-extract.c b/contrib/libunwind/src/mi/Ldyn-extract.c deleted file mode 100644 index 1802f865f77..00000000000 --- a/contrib/libunwind/src/mi/Ldyn-extract.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gdyn-extract.c" -#endif diff --git a/contrib/libunwind/src/mi/Ldyn-remote.c b/contrib/libunwind/src/mi/Ldyn-remote.c deleted file mode 100644 index 260722a04b2..00000000000 --- a/contrib/libunwind/src/mi/Ldyn-remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gdyn-remote.c" -#endif diff --git a/contrib/libunwind/src/mi/Lfind_dynamic_proc_info.c b/contrib/libunwind/src/mi/Lfind_dynamic_proc_info.c deleted file mode 100644 index bc88e1c53f0..00000000000 --- a/contrib/libunwind/src/mi/Lfind_dynamic_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gfind_dynamic_proc_info.c" -#endif diff --git a/contrib/libunwind/src/mi/Lget_accessors.c b/contrib/libunwind/src/mi/Lget_accessors.c deleted file mode 100644 index 555e37f30da..00000000000 --- a/contrib/libunwind/src/mi/Lget_accessors.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_accessors.c" -#endif diff --git a/contrib/libunwind/src/mi/Lget_fpreg.c b/contrib/libunwind/src/mi/Lget_fpreg.c deleted file mode 100644 index e3be4414378..00000000000 --- a/contrib/libunwind/src/mi/Lget_fpreg.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_fpreg.c" -#endif diff --git a/contrib/libunwind/src/mi/Lget_proc_info_by_ip.c b/contrib/libunwind/src/mi/Lget_proc_info_by_ip.c deleted file mode 100644 index 96910d83e45..00000000000 --- a/contrib/libunwind/src/mi/Lget_proc_info_by_ip.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info_by_ip.c" -#endif diff --git a/contrib/libunwind/src/mi/Lget_proc_name.c b/contrib/libunwind/src/mi/Lget_proc_name.c deleted file mode 100644 index 378097b57a0..00000000000 --- a/contrib/libunwind/src/mi/Lget_proc_name.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_name.c" -#endif diff --git a/contrib/libunwind/src/mi/Lget_reg.c b/contrib/libunwind/src/mi/Lget_reg.c deleted file mode 100644 index effe8a80635..00000000000 --- a/contrib/libunwind/src/mi/Lget_reg.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_reg.c" -#endif diff --git a/contrib/libunwind/src/mi/Lput_dynamic_unwind_info.c b/contrib/libunwind/src/mi/Lput_dynamic_unwind_info.c deleted file mode 100644 index 99597cd5fac..00000000000 --- a/contrib/libunwind/src/mi/Lput_dynamic_unwind_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gput_dynamic_unwind_info.c" -#endif diff --git a/contrib/libunwind/src/mi/Lset_cache_size.c b/contrib/libunwind/src/mi/Lset_cache_size.c deleted file mode 100644 index 670f64d3a9f..00000000000 --- a/contrib/libunwind/src/mi/Lset_cache_size.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gset_cache_size.c" -#endif diff --git a/contrib/libunwind/src/mi/Lset_caching_policy.c b/contrib/libunwind/src/mi/Lset_caching_policy.c deleted file mode 100644 index cc18816b377..00000000000 --- a/contrib/libunwind/src/mi/Lset_caching_policy.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gset_caching_policy.c" -#endif diff --git a/contrib/libunwind/src/mi/Lset_fpreg.c b/contrib/libunwind/src/mi/Lset_fpreg.c deleted file mode 100644 index 2497d404f46..00000000000 --- a/contrib/libunwind/src/mi/Lset_fpreg.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gset_fpreg.c" -#endif diff --git a/contrib/libunwind/src/mi/Lset_reg.c b/contrib/libunwind/src/mi/Lset_reg.c deleted file mode 100644 index c7a872b016f..00000000000 --- a/contrib/libunwind/src/mi/Lset_reg.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gset_reg.c" -#endif diff --git a/contrib/libunwind/src/mi/_ReadSLEB.c b/contrib/libunwind/src/mi/_ReadSLEB.c deleted file mode 100644 index c041e37a054..00000000000 --- a/contrib/libunwind/src/mi/_ReadSLEB.c +++ /dev/null @@ -1,25 +0,0 @@ -#include - -unw_word_t -_ReadSLEB (unsigned char **dpp) -{ - unsigned shift = 0; - unw_word_t byte, result = 0; - unsigned char *bp = *dpp; - - while (1) - { - byte = *bp++; - result |= (byte & 0x7f) << shift; - shift += 7; - if ((byte & 0x80) == 0) - break; - } - - if (shift < 8 * sizeof (unw_word_t) && (byte & 0x40) != 0) - /* sign-extend negative value */ - result |= ((unw_word_t) -1) << shift; - - *dpp = bp; - return result; -} diff --git a/contrib/libunwind/src/mi/_ReadULEB.c b/contrib/libunwind/src/mi/_ReadULEB.c deleted file mode 100644 index 116f3e19bc9..00000000000 --- a/contrib/libunwind/src/mi/_ReadULEB.c +++ /dev/null @@ -1,20 +0,0 @@ -#include - -unw_word_t -_ReadULEB (unsigned char **dpp) -{ - unsigned shift = 0; - unw_word_t byte, result = 0; - unsigned char *bp = *dpp; - - while (1) - { - byte = *bp++; - result |= (byte & 0x7f) << shift; - if ((byte & 0x80) == 0) - break; - shift += 7; - } - *dpp = bp; - return result; -} diff --git a/contrib/libunwind/src/mi/backtrace.c b/contrib/libunwind/src/mi/backtrace.c deleted file mode 100644 index c7aa2bdcdcb..00000000000 --- a/contrib/libunwind/src/mi/backtrace.c +++ /dev/null @@ -1,81 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef UNW_REMOTE_ONLY - -#define UNW_LOCAL_ONLY -#include -#include -#include - -/* See glibc manual for a description of this function. */ - -static ALWAYS_INLINE int -slow_backtrace (void **buffer, int size, unw_context_t *uc) -{ - unw_cursor_t cursor; - unw_word_t ip; - int n = 0; - - if (unlikely (unw_init_local (&cursor, uc) < 0)) - return 0; - - while (unw_step (&cursor) > 0) - { - if (n >= size) - return n; - - if (unw_get_reg (&cursor, UNW_REG_IP, &ip) < 0) - return n; - buffer[n++] = (void *) (uintptr_t) ip; - } - return n; -} - -int -unw_backtrace (void **buffer, int size) -{ - unw_cursor_t cursor; - unw_context_t uc; - int n = size; - - tdep_getcontext_trace (&uc); - - if (unlikely (unw_init_local (&cursor, &uc) < 0)) - return 0; - - if (unlikely (tdep_trace (&cursor, buffer, &n) < 0)) - { - unw_getcontext (&uc); - return slow_backtrace (buffer, size, &uc); - } - - return n; -} - -extern int backtrace (void **buffer, int size) - WEAK ALIAS(unw_backtrace); - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/mi/dyn-cancel.c b/contrib/libunwind/src/mi/dyn-cancel.c deleted file mode 100644 index 9d7472d5fdf..00000000000 --- a/contrib/libunwind/src/mi/dyn-cancel.c +++ /dev/null @@ -1,46 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -void -_U_dyn_cancel (unw_dyn_info_t *di) -{ - mutex_lock (&_U_dyn_info_list_lock); - { - ++_U_dyn_info_list.generation; - - if (di->prev) - di->prev->next = di->next; - else - _U_dyn_info_list.first = di->next; - - if (di->next) - di->next->prev = di->prev; - } - mutex_unlock (&_U_dyn_info_list_lock); - - di->next = di->prev = NULL; -} diff --git a/contrib/libunwind/src/mi/dyn-info-list.c b/contrib/libunwind/src/mi/dyn-info-list.c deleted file mode 100644 index 1a0790d3684..00000000000 --- a/contrib/libunwind/src/mi/dyn-info-list.c +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - -PROTECTED unw_word_t -_U_dyn_info_list_addr (void) -{ - return (unw_word_t) (uintptr_t) &_U_dyn_info_list; -} diff --git a/contrib/libunwind/src/mi/dyn-register.c b/contrib/libunwind/src/mi/dyn-register.c deleted file mode 100644 index efdad3de076..00000000000 --- a/contrib/libunwind/src/mi/dyn-register.c +++ /dev/null @@ -1,44 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2001-2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -HIDDEN define_lock (_U_dyn_info_list_lock); - -void -_U_dyn_register (unw_dyn_info_t *di) -{ - mutex_lock (&_U_dyn_info_list_lock); - { - ++_U_dyn_info_list.generation; - - di->next = _U_dyn_info_list.first; - di->prev = NULL; - if (di->next) - di->next->prev = di; - _U_dyn_info_list.first = di; - } - mutex_unlock (&_U_dyn_info_list_lock); -} diff --git a/contrib/libunwind/src/mi/flush_cache.c b/contrib/libunwind/src/mi/flush_cache.c deleted file mode 100644 index 513d13564fc..00000000000 --- a/contrib/libunwind/src/mi/flush_cache.c +++ /dev/null @@ -1,59 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED void -unw_flush_cache (unw_addr_space_t as, unw_word_t lo, unw_word_t hi) -{ -#if !UNW_TARGET_IA64 - struct unw_debug_frame_list *w = as->debug_frames; -#endif - - /* clear dyn_info_list_addr cache: */ - as->dyn_info_list_addr = 0; - -#if !UNW_TARGET_IA64 - for (; w; w = w->next) - { - if (w->index) - free (w->index); - free (w->debug_frame); - } - as->debug_frames = NULL; -#endif - - /* This lets us flush caches lazily. The implementation currently - ignores the flush range arguments (lo-hi). This is OK because - unw_flush_cache() is allowed to flush more than the requested - range. */ - -#ifdef HAVE_FETCH_AND_ADD - fetch_and_add1 (&as->cache_generation); -#else -# warning unw_flush_cache(): need a way to atomically increment an integer. - ++as->cache_generation; -#endif -} diff --git a/contrib/libunwind/src/mi/init.c b/contrib/libunwind/src/mi/init.c deleted file mode 100644 index 057027e0ec8..00000000000 --- a/contrib/libunwind/src/mi/init.c +++ /dev/null @@ -1,60 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -HIDDEN intrmask_t unwi_full_mask; - -static const char rcsid[] UNUSED = - "$Id: " PACKAGE_STRING " --- report bugs to " PACKAGE_BUGREPORT " $"; - -#if UNW_DEBUG - -/* Must not be declared HIDDEN/PROTECTED because libunwind.so and - libunwind-PLATFORM.so will both define their own copies of this - variable and we want to use only one or the other when both - libraries are loaded. */ -long unwi_debug_level; - -#endif /* UNW_DEBUG */ - -HIDDEN void -mi_init (void) -{ -#if UNW_DEBUG - const char *str = getenv ("UNW_DEBUG_LEVEL"); - - if (str) - unwi_debug_level = atoi (str); - - if (unwi_debug_level > 0) - { - setbuf (stdout, NULL); - setbuf (stderr, NULL); - } -#endif - - assert (sizeof (struct cursor) <= sizeof (unw_cursor_t)); -} diff --git a/contrib/libunwind/src/mi/mempool.c b/contrib/libunwind/src/mi/mempool.c deleted file mode 100644 index 536b64e8157..00000000000 --- a/contrib/libunwind/src/mi/mempool.c +++ /dev/null @@ -1,184 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2003, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -/* From GCC docs: ``Gcc also provides a target specific macro - * __BIGGEST_ALIGNMENT__, which is the largest alignment ever used for any data - * type on the target machine you are compiling for.'' */ -#ifdef __BIGGEST_ALIGNMENT__ -# define MAX_ALIGN __BIGGEST_ALIGNMENT__ -#else -/* Crude hack to check that MAX_ALIGN is power-of-two. - * sizeof(long double) = 12 on i386. */ -# define MAX_ALIGN_(n) (n < 8 ? 8 : \ - n < 16 ? 16 : n) -# define MAX_ALIGN MAX_ALIGN_(sizeof (long double)) -#endif - -static char sos_memory[SOS_MEMORY_SIZE] ALIGNED(MAX_ALIGN); -static size_t sos_memory_freepos; -static size_t pg_size; - -HIDDEN void * -sos_alloc (size_t size) -{ - size_t pos; - - size = UNW_ALIGN(size, MAX_ALIGN); - -#if defined(__GNUC__) && defined(HAVE_FETCH_AND_ADD) - /* Assume `sos_memory' is suitably aligned. */ - assert(((uintptr_t) &sos_memory[0] & (MAX_ALIGN-1)) == 0); - - pos = fetch_and_add (&sos_memory_freepos, size); -#else - static define_lock (sos_lock); - intrmask_t saved_mask; - - lock_acquire (&sos_lock, saved_mask); - { - /* No assumptions about `sos_memory' alignment. */ - if (sos_memory_freepos == 0) - { - unsigned align = UNW_ALIGN((uintptr_t) &sos_memory[0], MAX_ALIGN) - - (uintptr_t) &sos_memory[0]; - sos_memory_freepos = align; - } - pos = sos_memory_freepos; - sos_memory_freepos += size; - } - lock_release (&sos_lock, saved_mask); -#endif - - assert (((uintptr_t) &sos_memory[pos] & (MAX_ALIGN-1)) == 0); - assert ((pos+size) <= SOS_MEMORY_SIZE); - - return &sos_memory[pos]; -} - -/* Must be called while holding the mempool lock. */ - -static void -free_object (struct mempool *pool, void *object) -{ - struct object *obj = object; - - obj->next = pool->free_list; - pool->free_list = obj; - ++pool->num_free; -} - -static void -add_memory (struct mempool *pool, char *mem, size_t size, size_t obj_size) -{ - char *obj; - - for (obj = mem; obj <= mem + size - obj_size; obj += obj_size) - free_object (pool, obj); -} - -static void -expand (struct mempool *pool) -{ - size_t size; - char *mem; - - size = pool->chunk_size; - GET_MEMORY (mem, size); - if (!mem) - { - size = UNW_ALIGN(pool->obj_size, pg_size); - GET_MEMORY (mem, size); - if (!mem) - { - /* last chance: try to allocate one object from the SOS memory */ - size = pool->obj_size; - mem = sos_alloc (size); - } - } - add_memory (pool, mem, size, pool->obj_size); -} - -HIDDEN void -mempool_init (struct mempool *pool, size_t obj_size, size_t reserve) -{ - if (pg_size == 0) - pg_size = getpagesize (); - - memset (pool, 0, sizeof (*pool)); - - lock_init (&pool->lock); - - /* round object-size up to integer multiple of MAX_ALIGN */ - obj_size = UNW_ALIGN(obj_size, MAX_ALIGN); - - if (!reserve) - { - reserve = pg_size / obj_size / 4; - if (!reserve) - reserve = 16; - } - - pool->obj_size = obj_size; - pool->reserve = reserve; - pool->chunk_size = UNW_ALIGN(2*reserve*obj_size, pg_size); - - expand (pool); -} - -HIDDEN void * -mempool_alloc (struct mempool *pool) -{ - intrmask_t saved_mask; - struct object *obj; - - lock_acquire (&pool->lock, saved_mask); - { - if (pool->num_free <= pool->reserve) - expand (pool); - - assert (pool->num_free > 0); - - --pool->num_free; - obj = pool->free_list; - pool->free_list = obj->next; - } - lock_release (&pool->lock, saved_mask); - return obj; -} - -HIDDEN void -mempool_free (struct mempool *pool, void *object) -{ - intrmask_t saved_mask; - - lock_acquire (&pool->lock, saved_mask); - { - free_object (pool, object); - } - lock_release (&pool->lock, saved_mask); -} diff --git a/contrib/libunwind/src/mi/strerror.c b/contrib/libunwind/src/mi/strerror.c deleted file mode 100644 index 2cec73d1db9..00000000000 --- a/contrib/libunwind/src/mi/strerror.c +++ /dev/null @@ -1,51 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 BEA Systems - Contributed by Thomas Hallgren - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -/* Returns the text corresponding to the given err_code or the - text "invalid error code" if the err_code is invalid. */ -const char * -unw_strerror (int err_code) -{ - const char *cp; - unw_error_t error = (unw_error_t)-err_code; - switch (error) - { - case UNW_ESUCCESS: cp = "no error"; break; - case UNW_EUNSPEC: cp = "unspecified (general) error"; break; - case UNW_ENOMEM: cp = "out of memory"; break; - case UNW_EBADREG: cp = "bad register number"; break; - case UNW_EREADONLYREG: cp = "attempt to write read-only register"; break; - case UNW_ESTOPUNWIND: cp = "stop unwinding"; break; - case UNW_EINVALIDIP: cp = "invalid IP"; break; - case UNW_EBADFRAME: cp = "bad frame"; break; - case UNW_EINVAL: cp = "unsupported operation or bad value"; break; - case UNW_EBADVERSION: cp = "unwind info has unsupported version"; break; - case UNW_ENOINFO: cp = "no unwind info found"; break; - default: cp = "invalid error code"; - } - return cp; -} diff --git a/contrib/libunwind/src/mips/Gapply_reg_state.c b/contrib/libunwind/src/mips/Gapply_reg_state.c deleted file mode 100644 index eec93046f56..00000000000 --- a/contrib/libunwind/src/mips/Gapply_reg_state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); -} diff --git a/contrib/libunwind/src/mips/Gcreate_addr_space.c b/contrib/libunwind/src/mips/Gcreate_addr_space.c deleted file mode 100644 index 371841d900e..00000000000 --- a/contrib/libunwind/src/mips/Gcreate_addr_space.c +++ /dev/null @@ -1,66 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* - * MIPS supports only big or little-endian, not weird stuff like - * PDP_ENDIAN. - */ - if (byte_order != 0 - && byte_order != __LITTLE_ENDIAN - && byte_order != __BIG_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - if (byte_order == 0) - /* use host default: */ - as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); - else - as->big_endian = (byte_order == __BIG_ENDIAN); - - /* FIXME! There is no way to specify the ABI. */ - as->abi = UNW_MIPS_ABI_O32; - as->addr_size = 4; - - return as; -#endif -} diff --git a/contrib/libunwind/src/mips/Gget_proc_info.c b/contrib/libunwind/src/mips/Gget_proc_info.c deleted file mode 100644 index 973ddd979bd..00000000000 --- a/contrib/libunwind/src/mips/Gget_proc_info.c +++ /dev/null @@ -1,41 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - /* We can only unwind using Dwarf into on MIPS: return failure code - if it's not present. */ - ret = dwarf_make_proc_info (&c->dwarf); - if (ret < 0) - return ret; - - *pi = c->dwarf.pi; - return 0; -} diff --git a/contrib/libunwind/src/mips/Gget_save_loc.c b/contrib/libunwind/src/mips/Gget_save_loc.c deleted file mode 100644 index d6075b76cbb..00000000000 --- a/contrib/libunwind/src/mips/Gget_save_loc.c +++ /dev/null @@ -1,100 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -/* FIXME for MIPS. */ - -PROTECTED int -unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) -{ - struct cursor *c = (struct cursor *) cursor; - dwarf_loc_t loc; - - loc = DWARF_NULL_LOC; /* default to "not saved" */ - - switch (reg) - { - case UNW_MIPS_R0: - case UNW_MIPS_R1: - case UNW_MIPS_R2: - case UNW_MIPS_R3: - case UNW_MIPS_R4: - case UNW_MIPS_R5: - case UNW_MIPS_R6: - case UNW_MIPS_R7: - case UNW_MIPS_R8: - case UNW_MIPS_R9: - case UNW_MIPS_R10: - case UNW_MIPS_R11: - case UNW_MIPS_R12: - case UNW_MIPS_R13: - case UNW_MIPS_R14: - case UNW_MIPS_R15: - case UNW_MIPS_R16: - case UNW_MIPS_R17: - case UNW_MIPS_R18: - case UNW_MIPS_R19: - case UNW_MIPS_R20: - case UNW_MIPS_R21: - case UNW_MIPS_R22: - case UNW_MIPS_R23: - case UNW_MIPS_R24: - case UNW_MIPS_R25: - case UNW_MIPS_R26: - case UNW_MIPS_R27: - case UNW_MIPS_R28: - case UNW_MIPS_R29: - case UNW_MIPS_R30: - case UNW_MIPS_R31: - case UNW_MIPS_PC: - loc = c->dwarf.loc[reg - UNW_MIPS_R0]; - break; - - default: - break; - } - - memset (sloc, 0, sizeof (*sloc)); - - if (DWARF_IS_NULL_LOC (loc)) - { - sloc->type = UNW_SLT_NONE; - return 0; - } - -#if !defined(UNW_LOCAL_ONLY) - if (DWARF_IS_REG_LOC (loc)) - { - sloc->type = UNW_SLT_REG; - sloc->u.regnum = DWARF_GET_LOC (loc); - } - else -#endif - { - sloc->type = UNW_SLT_MEMORY; - sloc->u.addr = DWARF_GET_LOC (loc); - } - return 0; -} diff --git a/contrib/libunwind/src/mips/Gglobal.c b/contrib/libunwind/src/mips/Gglobal.c deleted file mode 100644 index fa9478eebe7..00000000000 --- a/contrib/libunwind/src/mips/Gglobal.c +++ /dev/null @@ -1,55 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "dwarf_i.h" - -HIDDEN define_lock (mips_lock); -HIDDEN int tdep_init_done; - -HIDDEN void -tdep_init (void) -{ - intrmask_t saved_mask; - - sigfillset (&unwi_full_mask); - - lock_acquire (&mips_lock, saved_mask); - { - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - mi_init (); - - dwarf_init (); - -#ifndef UNW_REMOTE_ONLY - mips_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - } - out: - lock_release (&mips_lock, saved_mask); -} diff --git a/contrib/libunwind/src/mips/Ginit.c b/contrib/libunwind/src/mips/Ginit.c deleted file mode 100644 index 077a386c6e8..00000000000 --- a/contrib/libunwind/src/mips/Ginit.c +++ /dev/null @@ -1,210 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -PROTECTED unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; - -/* Return the address of the 64-bit slot in UC for REG (even for o32, - where registers are 32-bit, the slots are still 64-bit). */ - -static inline void * -uc_addr (ucontext_t *uc, int reg) -{ - if (reg >= UNW_MIPS_R0 && reg < UNW_MIPS_R0 + 32) - return &uc->uc_mcontext.gregs[reg - UNW_MIPS_R0]; - else if (reg == UNW_MIPS_PC) - return &uc->uc_mcontext.pc; - else - return NULL; -} - -# ifdef UNW_LOCAL_ONLY - -HIDDEN void * -tdep_uc_addr (ucontext_t *uc, int reg) -{ - char *addr = uc_addr (uc, reg); - - if (((reg >= UNW_MIPS_R0 && reg <= UNW_MIPS_R31) || reg == UNW_MIPS_PC) - && tdep_big_endian (unw_local_addr_space) - && unw_local_addr_space->abi == UNW_MIPS_ABI_O32) - addr += 4; - - return addr; -} - -# endif /* UNW_LOCAL_ONLY */ - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - -/* XXX fix me: there is currently no way to locate the dyn-info list - by a remote unwinder. On ia64, this is done via a special - unwind-table entry. Perhaps something similar can be done with - DWARF2 unwind info. */ - -static void -put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ - *dyn_info_list_addr = (unw_word_t) (intptr_t) &_U_dyn_info_list; - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - if (write) - { - Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val); - *(unw_word_t *) (intptr_t) addr = *val; - } - else - { - *val = *(unw_word_t *) (intptr_t) addr; - Debug (16, "mem[%llx] -> %llx\n", (long long) addr, (long long) *val); - } - return 0; -} - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, - void *arg) -{ - unw_word_t *addr; - ucontext_t *uc = arg; - - if (unw_is_fpreg (reg)) - goto badreg; - - Debug (16, "reg = %s\n", unw_regname (reg)); - if (!(addr = uc_addr (uc, reg))) - goto badreg; - - if (write) - { - *(unw_word_t *) (intptr_t) addr = (mips_reg_t) *val; - Debug (12, "%s <- %llx\n", unw_regname (reg), (long long) *val); - } - else - { - *val = (mips_reg_t) *(unw_word_t *) (intptr_t) addr; - Debug (12, "%s -> %llx\n", unw_regname (reg), (long long) *val); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - ucontext_t *uc = arg; - unw_fpreg_t *addr; - - if (!unw_is_fpreg (reg)) - goto badreg; - - if (!(addr = uc_addr (uc, reg))) - goto badreg; - - if (write) - { - Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - *(unw_fpreg_t *) (intptr_t) addr = *val; - } - else - { - *val = *(unw_fpreg_t *) (intptr_t) addr; - Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - /* attempt to access a non-preserved register */ - return -UNW_EBADREG; -} - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - - return elf_w (get_proc_name) (as, getpid (), ip, buf, buf_len, offp); -} - -HIDDEN void -mips_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); -#if _MIPS_SIM == _ABIO32 - local_addr_space.abi = UNW_MIPS_ABI_O32; -#elif _MIPS_SIM == _ABIN32 - local_addr_space.abi = UNW_MIPS_ABI_N32; -#elif _MIPS_SIM == _ABI64 - local_addr_space.abi = UNW_MIPS_ABI_N64; -#else -# error Unsupported ABI -#endif - local_addr_space.addr_size = sizeof (void *); - local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; - local_addr_space.acc.find_proc_info = dwarf_find_proc_info; - local_addr_space.acc.put_unwind_info = put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = NULL; /* mips_local_resume? FIXME! */ - local_addr_space.acc.get_proc_name = get_static_proc_name; - unw_flush_cache (&local_addr_space, 0, 0); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/mips/Ginit_local.c b/contrib/libunwind/src/mips/Ginit_local.c deleted file mode 100644 index a29b6d09b7a..00000000000 --- a/contrib/libunwind/src/mips/Ginit_local.c +++ /dev/null @@ -1,76 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "init.h" - -#ifdef UNW_REMOTE_ONLY - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - return -UNW_EINVAL; -} - -#else /* !UNW_REMOTE_ONLY */ - -static int -unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) -{ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = unw_local_addr_space; - c->dwarf.as_arg = uc; - return common_init (c, use_prev_instr); -} - -PROTECTED int -unw_init_local(unw_cursor_t *cursor, ucontext_t *uc) -{ - return unw_init_local_common(cursor, uc, 1); -} - -PROTECTED int -unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) -{ - if (!flag) - { - return unw_init_local_common(cursor, uc, 1); - } - else if (flag == UNW_INIT_SIGNAL_FRAME) - { - return unw_init_local_common(cursor, uc, 0); - } - else - { - return -UNW_EINVAL; - } -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/mips/Ginit_remote.c b/contrib/libunwind/src/mips/Ginit_remote.c deleted file mode 100644 index f284e994f4b..00000000000 --- a/contrib/libunwind/src/mips/Ginit_remote.c +++ /dev/null @@ -1,45 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "init.h" -#include "unwind_i.h" - -PROTECTED int -unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) -{ -#ifdef UNW_LOCAL_ONLY - return -UNW_EINVAL; -#else /* !UNW_LOCAL_ONLY */ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = as; - c->dwarf.as_arg = as_arg; - return common_init (c, 0); -#endif /* !UNW_LOCAL_ONLY */ -} diff --git a/contrib/libunwind/src/mips/Gis_signal_frame.c b/contrib/libunwind/src/mips/Gis_signal_frame.c deleted file mode 100644 index 2c9627f4464..00000000000 --- a/contrib/libunwind/src/mips/Gis_signal_frame.c +++ /dev/null @@ -1,78 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2015 Imagination Technologies Limited - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, w1, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - ip = c->dwarf.ip; - - /* syscall */ - if ((ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) - return 0; - if ((w1 & 0xffffffff) != 0x0c) - return 0; - - /* li v0, 0x1061 (rt) or li v0, 0x1017 */ - if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0) - return 0; - - switch (c->dwarf.as->abi) - { - case UNW_MIPS_ABI_O32: - switch (w0 & 0xffffffff) - { - case 0x24021061: - return 1; - case 0x24021017: - return 2; - default: - return 0; - } - case UNW_MIPS_ABI_N64: - switch (w0 & 0xffffffff) - { - case 0x2402145b: - return 1; - default: - return 0; - } - default: - return 0; - } -} diff --git a/contrib/libunwind/src/mips/Greg_states_iterate.c b/contrib/libunwind/src/mips/Greg_states_iterate.c deleted file mode 100644 index a39837a1781..00000000000 --- a/contrib/libunwind/src/mips/Greg_states_iterate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_reg_states_iterate (&c->dwarf, cb, token); -} diff --git a/contrib/libunwind/src/mips/Gregs.c b/contrib/libunwind/src/mips/Gregs.c deleted file mode 100644 index 95194022d2b..00000000000 --- a/contrib/libunwind/src/mips/Gregs.c +++ /dev/null @@ -1,105 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -/* FIXME: The following is probably unfinished and/or at least partly bogus. */ - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - dwarf_loc_t loc = DWARF_NULL_LOC; - - switch (reg) - { - case UNW_MIPS_R0: - case UNW_MIPS_R1: - case UNW_MIPS_R2: - case UNW_MIPS_R3: - case UNW_MIPS_R4: - case UNW_MIPS_R5: - case UNW_MIPS_R6: - case UNW_MIPS_R7: - case UNW_MIPS_R8: - case UNW_MIPS_R9: - case UNW_MIPS_R10: - case UNW_MIPS_R11: - case UNW_MIPS_R12: - case UNW_MIPS_R13: - case UNW_MIPS_R14: - case UNW_MIPS_R15: - case UNW_MIPS_R16: - case UNW_MIPS_R17: - case UNW_MIPS_R18: - case UNW_MIPS_R19: - case UNW_MIPS_R20: - case UNW_MIPS_R21: - case UNW_MIPS_R22: - case UNW_MIPS_R23: - case UNW_MIPS_R24: - case UNW_MIPS_R25: - case UNW_MIPS_R26: - case UNW_MIPS_R27: - case UNW_MIPS_R28: - case UNW_MIPS_R29: - case UNW_MIPS_R30: - case UNW_MIPS_R31: - loc = c->dwarf.loc[reg - UNW_MIPS_R0]; - break; - - case UNW_MIPS_PC: - if (write) - c->dwarf.ip = *valp; /* update the IP cache */ - loc = c->dwarf.loc[reg]; - break; - - case UNW_MIPS_CFA: - if (write) - return -UNW_EREADONLYREG; - *valp = c->dwarf.cfa; - return 0; - - /* FIXME: IP? Copro & shadow registers? */ - - default: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; - } - - if (write) - return dwarf_put (&c->dwarf, loc, *valp); - else - return dwarf_get (&c->dwarf, loc, valp); -} - -/* FIXME for MIPS. */ - -HIDDEN int -tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, - int write) -{ - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} diff --git a/contrib/libunwind/src/mips/Gresume.c b/contrib/libunwind/src/mips/Gresume.c deleted file mode 100644 index b822e24b0c5..00000000000 --- a/contrib/libunwind/src/mips/Gresume.c +++ /dev/null @@ -1,45 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* FIXME for MIPS. */ - -#include - -#include "unwind_i.h" - -#ifndef UNW_REMOTE_ONLY - -HIDDEN inline int -mips_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ - return -UNW_EINVAL; -} - -#endif /* !UNW_REMOTE_ONLY */ - -PROTECTED int -unw_resume (unw_cursor_t *cursor) -{ - return -UNW_EINVAL; -} diff --git a/contrib/libunwind/src/mips/Gstep.c b/contrib/libunwind/src/mips/Gstep.c deleted file mode 100644 index 0a67492fe99..00000000000 --- a/contrib/libunwind/src/mips/Gstep.c +++ /dev/null @@ -1,132 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2015 Imagination Technologies Limited - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" - -PROTECTED int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t sc_addr, sp_addr = c->dwarf.cfa; - unw_word_t ra, fp; - int ret; - - switch (unw_is_signal_frame (cursor)) { - case 1: - sc_addr = sp_addr + LINUX_SF_TRAMP_SIZE + sizeof (siginfo_t) + - LINUX_UC_MCONTEXT_OFF; - break; - case 2: - sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF; - break; - default: - return -UNW_EUNSPEC; - } - - if (tdep_big_endian(c->dwarf.as)) - sc_addr += 4; - - c->sigcontext_addr = sc_addr; - - /* Update the dwarf cursor. */ - c->dwarf.loc[UNW_MIPS_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); - c->dwarf.loc[UNW_MIPS_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); - c->dwarf.loc[UNW_MIPS_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); - c->dwarf.loc[UNW_MIPS_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); - c->dwarf.loc[UNW_MIPS_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); - c->dwarf.loc[UNW_MIPS_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); - c->dwarf.loc[UNW_MIPS_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); - c->dwarf.loc[UNW_MIPS_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); - c->dwarf.loc[UNW_MIPS_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); - c->dwarf.loc[UNW_MIPS_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); - c->dwarf.loc[UNW_MIPS_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); - c->dwarf.loc[UNW_MIPS_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0); - c->dwarf.loc[UNW_MIPS_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0); - c->dwarf.loc[UNW_MIPS_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0); - c->dwarf.loc[UNW_MIPS_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0); - c->dwarf.loc[UNW_MIPS_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0); - c->dwarf.loc[UNW_MIPS_R16] = DWARF_LOC (sc_addr + LINUX_SC_R16_OFF, 0); - c->dwarf.loc[UNW_MIPS_R17] = DWARF_LOC (sc_addr + LINUX_SC_R17_OFF, 0); - c->dwarf.loc[UNW_MIPS_R18] = DWARF_LOC (sc_addr + LINUX_SC_R18_OFF, 0); - c->dwarf.loc[UNW_MIPS_R19] = DWARF_LOC (sc_addr + LINUX_SC_R19_OFF, 0); - c->dwarf.loc[UNW_MIPS_R20] = DWARF_LOC (sc_addr + LINUX_SC_R20_OFF, 0); - c->dwarf.loc[UNW_MIPS_R21] = DWARF_LOC (sc_addr + LINUX_SC_R21_OFF, 0); - c->dwarf.loc[UNW_MIPS_R22] = DWARF_LOC (sc_addr + LINUX_SC_R22_OFF, 0); - c->dwarf.loc[UNW_MIPS_R23] = DWARF_LOC (sc_addr + LINUX_SC_R23_OFF, 0); - c->dwarf.loc[UNW_MIPS_R24] = DWARF_LOC (sc_addr + LINUX_SC_R24_OFF, 0); - c->dwarf.loc[UNW_MIPS_R25] = DWARF_LOC (sc_addr + LINUX_SC_R25_OFF, 0); - c->dwarf.loc[UNW_MIPS_R26] = DWARF_LOC (sc_addr + LINUX_SC_R26_OFF, 0); - c->dwarf.loc[UNW_MIPS_R27] = DWARF_LOC (sc_addr + LINUX_SC_R27_OFF, 0); - c->dwarf.loc[UNW_MIPS_R28] = DWARF_LOC (sc_addr + LINUX_SC_R28_OFF, 0); - c->dwarf.loc[UNW_MIPS_R29] = DWARF_LOC (sc_addr + LINUX_SC_R29_OFF, 0); - c->dwarf.loc[UNW_MIPS_R30] = DWARF_LOC (sc_addr + LINUX_SC_R30_OFF, 0); - c->dwarf.loc[UNW_MIPS_R31] = DWARF_LOC (sc_addr + LINUX_SC_R31_OFF, 0); - c->dwarf.loc[UNW_MIPS_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); - - /* Set SP/CFA and PC/IP. */ - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_MIPS_R29], &c->dwarf.cfa); - - if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_PC_OFF, 0), - &c->dwarf.ip)) < 0) - return ret; - - if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R31_OFF, 0), - &ra)) < 0) - return ret; - if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R30_OFF, 0), - &fp)) < 0) - return ret; - - Debug (2, "SH (ip=0x%016llx, ra=0x%016llx, sp=0x%016llx, fp=0x%016llx)\n", - (unsigned long long)c->dwarf.ip, (unsigned long long)ra, - (unsigned long long)c->dwarf.cfa, (unsigned long long)fp); - - c->dwarf.pi_valid = 0; - c->dwarf.use_prev_instr = 0; - - return 1; -} - -PROTECTED int -unw_step (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - ret = unw_handle_signal_frame (cursor); - if (ret < 0) - /* Not a signal frame, try DWARF-based unwinding. */ - ret = dwarf_step (&c->dwarf); - - if (unlikely (ret == -UNW_ESTOPUNWIND)) - return ret; - - /* Dwarf unwinding didn't work, stop. */ - if (unlikely (ret < 0)) - return 0; - - return (c->dwarf.ip == 0) ? 0 : 1; -} diff --git a/contrib/libunwind/src/mips/Lapply_reg_state.c b/contrib/libunwind/src/mips/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/mips/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/mips/Lcreate_addr_space.c b/contrib/libunwind/src/mips/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901..00000000000 --- a/contrib/libunwind/src/mips/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/contrib/libunwind/src/mips/Lget_proc_info.c b/contrib/libunwind/src/mips/Lget_proc_info.c deleted file mode 100644 index 69028b019fc..00000000000 --- a/contrib/libunwind/src/mips/Lget_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info.c" -#endif diff --git a/contrib/libunwind/src/mips/Lget_save_loc.c b/contrib/libunwind/src/mips/Lget_save_loc.c deleted file mode 100644 index 9ea048a9076..00000000000 --- a/contrib/libunwind/src/mips/Lget_save_loc.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_save_loc.c" -#endif diff --git a/contrib/libunwind/src/mips/Lglobal.c b/contrib/libunwind/src/mips/Lglobal.c deleted file mode 100644 index 6d7b489e14b..00000000000 --- a/contrib/libunwind/src/mips/Lglobal.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/contrib/libunwind/src/mips/Linit.c b/contrib/libunwind/src/mips/Linit.c deleted file mode 100644 index e9abfdd46a3..00000000000 --- a/contrib/libunwind/src/mips/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/contrib/libunwind/src/mips/Linit_local.c b/contrib/libunwind/src/mips/Linit_local.c deleted file mode 100644 index 68a1687e854..00000000000 --- a/contrib/libunwind/src/mips/Linit_local.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_local.c" -#endif diff --git a/contrib/libunwind/src/mips/Linit_remote.c b/contrib/libunwind/src/mips/Linit_remote.c deleted file mode 100644 index 58cb04ab7cd..00000000000 --- a/contrib/libunwind/src/mips/Linit_remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_remote.c" -#endif diff --git a/contrib/libunwind/src/mips/Lis_signal_frame.c b/contrib/libunwind/src/mips/Lis_signal_frame.c deleted file mode 100644 index b9a7c4f51ad..00000000000 --- a/contrib/libunwind/src/mips/Lis_signal_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gis_signal_frame.c" -#endif diff --git a/contrib/libunwind/src/mips/Lreg_states_iterate.c b/contrib/libunwind/src/mips/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/mips/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/mips/Lregs.c b/contrib/libunwind/src/mips/Lregs.c deleted file mode 100644 index 2c9c75cd7d9..00000000000 --- a/contrib/libunwind/src/mips/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/contrib/libunwind/src/mips/Lresume.c b/contrib/libunwind/src/mips/Lresume.c deleted file mode 100644 index 41a8cf003de..00000000000 --- a/contrib/libunwind/src/mips/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/contrib/libunwind/src/mips/Lstep.c b/contrib/libunwind/src/mips/Lstep.c deleted file mode 100644 index c1ac3c7547f..00000000000 --- a/contrib/libunwind/src/mips/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/contrib/libunwind/src/mips/elfxx.c b/contrib/libunwind/src/mips/elfxx.c deleted file mode 100644 index 07d3d12b94f..00000000000 --- a/contrib/libunwind/src/mips/elfxx.c +++ /dev/null @@ -1,27 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -#include "../src/elfxx.c" diff --git a/contrib/libunwind/src/mips/gen-offsets.c b/contrib/libunwind/src/mips/gen-offsets.c deleted file mode 100644 index 448f6945326..00000000000 --- a/contrib/libunwind/src/mips/gen-offsets.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include - -#define UC(N,X) \ - printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X)) - -#define SC(N,X) \ - printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X)) - -int -main (void) -{ - printf ( -"/* Linux-specific definitions: */\n\n" - -"/* Define various structure offsets to simplify cross-compilation. */\n\n" - -"/* Offsets for MIPS Linux \"ucontext_t\": */\n\n"); - - UC ("FLAGS", uc_flags); - UC ("LINK", uc_link); - UC ("STACK", uc_stack); - UC ("MCONTEXT", uc_mcontext); - UC ("SIGMASK", uc_sigmask); - - UC ("MCONTEXT_GREGS", uc_mcontext.gregs); - - return 0; -} diff --git a/contrib/libunwind/src/mips/getcontext.S b/contrib/libunwind/src/mips/getcontext.S deleted file mode 100644 index d1dbd57932d..00000000000 --- a/contrib/libunwind/src/mips/getcontext.S +++ /dev/null @@ -1,93 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "offsets.h" -#include - - .text - -#if _MIPS_SIM == _ABIO32 -# if __BYTE_ORDER == __BIG_ENDIAN -# define OFFSET 4 -# else -# define OFFSET 0 -# endif -# define SREG(X) \ - sw $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X + OFFSET) ($4); \ - sra $1, $X, 31; \ - sw $1, (LINUX_UC_MCONTEXT_GREGS + 8 * X + 4 - OFFSET) ($4) -/* Yes, we save the return address to PC. */ -# define SPC \ - sw $31, (LINUX_UC_MCONTEXT_PC + OFFSET) ($4); \ - sra $1, $31, 31; \ - sw $1, (LINUX_UC_MCONTEXT_PC + 4 - OFFSET) ($4) -#else -# define SREG(X) sd $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X) ($4) -# define SPC sd $31, (LINUX_UC_MCONTEXT_PC) ($4) -#endif - - .global _Umips_getcontext - .type _Umips_getcontext, %function - # This is a stub version of getcontext() for MIPS which only stores core - # registers. -_Umips_getcontext: - .set noat - SREG (1) - SREG (0) - SREG (2) - SREG (3) - SREG (4) - SREG (5) - SREG (6) - SREG (7) - SREG (8) - SREG (9) - SREG (10) - SREG (11) - SREG (12) - SREG (13) - SREG (14) - SREG (15) - SREG (16) - SREG (17) - SREG (18) - SREG (19) - SREG (20) - SREG (21) - SREG (22) - SREG (23) - SREG (24) - SREG (25) - SREG (26) - SREG (27) - SREG (28) - SREG (29) - SREG (30) - SREG (31) - SPC - li $2, 0 - j $31 - - .size _Umips_getcontext, .-_Umips_getcontext diff --git a/contrib/libunwind/src/mips/init.h b/contrib/libunwind/src/mips/init.h deleted file mode 100644 index 30c193a18f7..00000000000 --- a/contrib/libunwind/src/mips/init.h +++ /dev/null @@ -1,59 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static inline int -common_init (struct cursor *c, unsigned use_prev_instr) -{ - int ret, i; - - for (i = 0; i < 32; i++) - c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, UNW_MIPS_R0 + i); - for (i = 32; i < DWARF_NUM_PRESERVED_REGS; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - - c->dwarf.loc[UNW_MIPS_PC] = DWARF_REG_LOC (&c->dwarf, UNW_MIPS_PC); - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_MIPS_PC], &c->dwarf.ip); - if (ret < 0) - return ret; - - ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_MIPS_R29), - &c->dwarf.cfa); - if (ret < 0) - return ret; - - /* FIXME: Initialisation for other registers. */ - - c->dwarf.args_size = 0; - c->dwarf.stash_frames = 0; - c->dwarf.use_prev_instr = use_prev_instr; - c->dwarf.pi_valid = 0; - c->dwarf.pi_is_dynamic = 0; - c->dwarf.hint = 0; - c->dwarf.prev_rs = 0; - - return 0; -} diff --git a/contrib/libunwind/src/mips/is_fpreg.c b/contrib/libunwind/src/mips/is_fpreg.c deleted file mode 100644 index 3acc6967a28..00000000000 --- a/contrib/libunwind/src/mips/is_fpreg.c +++ /dev/null @@ -1,35 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -/* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful - on MIPS. */ - -PROTECTED int -unw_is_fpreg (int regnum) -{ - /* FIXME: Support FP. */ - return 0; -} diff --git a/contrib/libunwind/src/mips/offsets.h b/contrib/libunwind/src/mips/offsets.h deleted file mode 100644 index b5060513677..00000000000 --- a/contrib/libunwind/src/mips/offsets.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Linux-specific definitions: */ - -/* Define various structure offsets to simplify cross-compilation. */ - -/* FIXME: Currently these are only used in getcontext.S, which is only used - for a local unwinder, so we can use the compile-time ABI. At a later date - we will want all three here, to use for signal handlers. Also, because - of the three ABIs, gen-offsets.c can not quite generate this file. */ - -/* Offsets for MIPS Linux "ucontext_t": */ - -/* First 24 bytes in sigframe are argument save space and padding for -what used to be signal trampolines. Ref: arch/mips/kernel/signal.c */ -#define LINUX_SF_TRAMP_SIZE 0x18 - -#if _MIPS_SIM == _ABIO32 - -# define LINUX_UC_FLAGS_OFF 0x0 -# define LINUX_UC_LINK_OFF 0x4 -# define LINUX_UC_STACK_OFF 0x8 -# define LINUX_UC_MCONTEXT_OFF 0x18 -# define LINUX_UC_SIGMASK_OFF 0x268 -# define LINUX_UC_MCONTEXT_PC 0x20 -# define LINUX_UC_MCONTEXT_GREGS 0x28 - -#elif _MIPS_SIM == _ABIN32 - -# define LINUX_UC_FLAGS_OFF 0x0 -# define LINUX_UC_LINK_OFF 0x4 -# define LINUX_UC_STACK_OFF 0x8 -# define LINUX_UC_MCONTEXT_OFF 0x18 -# define LINUX_UC_SIGMASK_OFF 0x270 -# define LINUX_UC_MCONTEXT_PC 0x258 -# define LINUX_UC_MCONTEXT_GREGS 0x18 - -#elif _MIPS_SIM == _ABI64 - -# define LINUX_UC_FLAGS_OFF 0x0 -# define LINUX_UC_LINK_OFF 0x8 -# define LINUX_UC_STACK_OFF 0x10 -# define LINUX_UC_MCONTEXT_OFF 0x28 -# define LINUX_UC_SIGMASK_OFF 0x280 -# define LINUX_UC_MCONTEXT_PC 0x268 -# define LINUX_UC_MCONTEXT_GREGS 0x28 - -#else - -#error Unsupported ABI - -#endif - -#define LINUX_SC_R0_OFF (LINUX_UC_MCONTEXT_GREGS - LINUX_UC_MCONTEXT_OFF) -#define LINUX_SC_R1_OFF (LINUX_SC_R0_OFF + 1*8) -#define LINUX_SC_R2_OFF (LINUX_SC_R0_OFF + 2*8) -#define LINUX_SC_R3_OFF (LINUX_SC_R0_OFF + 3*8) -#define LINUX_SC_R4_OFF (LINUX_SC_R0_OFF + 4*8) -#define LINUX_SC_R5_OFF (LINUX_SC_R0_OFF + 5*8) -#define LINUX_SC_R6_OFF (LINUX_SC_R0_OFF + 6*8) -#define LINUX_SC_R7_OFF (LINUX_SC_R0_OFF + 7*8) -#define LINUX_SC_R8_OFF (LINUX_SC_R0_OFF + 8*8) -#define LINUX_SC_R9_OFF (LINUX_SC_R0_OFF + 9*8) -#define LINUX_SC_R10_OFF (LINUX_SC_R0_OFF + 10*8) -#define LINUX_SC_R11_OFF (LINUX_SC_R0_OFF + 11*8) -#define LINUX_SC_R12_OFF (LINUX_SC_R0_OFF + 12*8) -#define LINUX_SC_R13_OFF (LINUX_SC_R0_OFF + 13*8) -#define LINUX_SC_R14_OFF (LINUX_SC_R0_OFF + 14*8) -#define LINUX_SC_R15_OFF (LINUX_SC_R0_OFF + 15*8) -#define LINUX_SC_R16_OFF (LINUX_SC_R0_OFF + 16*8) -#define LINUX_SC_R17_OFF (LINUX_SC_R0_OFF + 17*8) -#define LINUX_SC_R18_OFF (LINUX_SC_R0_OFF + 18*8) -#define LINUX_SC_R19_OFF (LINUX_SC_R0_OFF + 19*8) -#define LINUX_SC_R20_OFF (LINUX_SC_R0_OFF + 20*8) -#define LINUX_SC_R21_OFF (LINUX_SC_R0_OFF + 21*8) -#define LINUX_SC_R22_OFF (LINUX_SC_R0_OFF + 22*8) -#define LINUX_SC_R23_OFF (LINUX_SC_R0_OFF + 23*8) -#define LINUX_SC_R24_OFF (LINUX_SC_R0_OFF + 24*8) -#define LINUX_SC_R25_OFF (LINUX_SC_R0_OFF + 25*8) -#define LINUX_SC_R26_OFF (LINUX_SC_R0_OFF + 26*8) -#define LINUX_SC_R27_OFF (LINUX_SC_R0_OFF + 27*8) -#define LINUX_SC_R28_OFF (LINUX_SC_R0_OFF + 28*8) -#define LINUX_SC_R29_OFF (LINUX_SC_R0_OFF + 29*8) -#define LINUX_SC_R30_OFF (LINUX_SC_R0_OFF + 30*8) -#define LINUX_SC_R31_OFF (LINUX_SC_R0_OFF + 31*8) - -#define LINUX_SC_SP_OFF LINUX_SC_R29_OFF -#define LINUX_SC_PC_OFF (LINUX_UC_MCONTEXT_PC - LINUX_UC_MCONTEXT_OFF) diff --git a/contrib/libunwind/src/mips/regname.c b/contrib/libunwind/src/mips/regname.c deleted file mode 100644 index a4a63340d93..00000000000 --- a/contrib/libunwind/src/mips/regname.c +++ /dev/null @@ -1,48 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static const char *regname[] = - { - /* 0. */ - "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", - /* 8. */ - "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", - /* 16. */ - "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", - /* 24. */ - "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31", - }; - -PROTECTED const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) - return regname[reg]; - else if (reg == UNW_MIPS_PC) - return "pc"; - else - return "???"; -} diff --git a/contrib/libunwind/src/mips/siglongjmp.S b/contrib/libunwind/src/mips/siglongjmp.S deleted file mode 100644 index 9cbcf3dc014..00000000000 --- a/contrib/libunwind/src/mips/siglongjmp.S +++ /dev/null @@ -1,8 +0,0 @@ - /* Dummy implementation for now. */ - - .globl _UI_siglongjmp_cont - .globl _UI_longjmp_cont - -_UI_siglongjmp_cont: -_UI_longjmp_cont: - j $31 diff --git a/contrib/libunwind/src/mips/unwind_i.h b/contrib/libunwind/src/mips/unwind_i.h deleted file mode 100644 index 3382dcfe58c..00000000000 --- a/contrib/libunwind/src/mips/unwind_i.h +++ /dev/null @@ -1,43 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include - -#include - -#include "libunwind_i.h" - -#define mips_lock UNW_OBJ(lock) -#define mips_local_resume UNW_OBJ(local_resume) -#define mips_local_addr_space_init UNW_OBJ(local_addr_space_init) - -extern int mips_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, - void *arg); - -extern void mips_local_addr_space_init (void); - -#endif /* unwind_i_h */ diff --git a/contrib/libunwind/src/os-freebsd.c b/contrib/libunwind/src/os-freebsd.c deleted file mode 100644 index 2e59731e5d2..00000000000 --- a/contrib/libunwind/src/os-freebsd.c +++ /dev/null @@ -1,166 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2010 Konstantin Belousov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include -#include -#include -#include -#include -#include - -#include "libunwind_i.h" - -static void * -get_mem(size_t sz) -{ - void *res; - - res = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); - if (res == MAP_FAILED) - return (NULL); - return (res); -} - -static void -free_mem(void *ptr, size_t sz) -{ - munmap(ptr, sz); -} - -static int -get_pid_by_tid(int tid) -{ - int mib[3], error; - size_t len, len1; - char *buf; - struct kinfo_proc *kv; - unsigned i, pid; - - len = 0; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_ALL; - - error = sysctl(mib, 3, NULL, &len, NULL, 0); - if (error == -1) - return (-1); - len1 = len * 4 / 3; - buf = get_mem(len1); - if (buf == NULL) - return (-1); - len = len1; - error = sysctl(mib, 3, buf, &len, NULL, 0); - if (error == -1) { - free_mem(buf, len1); - return (-1); - } - pid = -1; - for (i = 0, kv = (struct kinfo_proc *)buf; i < len / sizeof(*kv); - i++, kv++) { - if (kv->ki_tid == tid) { - pid = kv->ki_pid; - break; - } - } - free_mem(buf, len1); - return (pid); -} - -PROTECTED int -tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, char *path, size_t pathlen) -{ - int mib[4], error, ret; - size_t len, len1; - char *buf, *bp, *eb; - struct kinfo_vmentry *kv; - - len = 0; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_VMMAP; - mib[3] = pid; - - error = sysctl(mib, 4, NULL, &len, NULL, 0); - if (error == -1) { - if (errno == ESRCH) { - mib[3] = get_pid_by_tid(pid); - if (mib[3] != -1) - error = sysctl(mib, 4, NULL, &len, NULL, 0); - if (error == -1) - return (-UNW_EUNSPEC); - } else - return (-UNW_EUNSPEC); - } - len1 = len * 4 / 3; - buf = get_mem(len1); - if (buf == NULL) - return (-UNW_EUNSPEC); - len = len1; - error = sysctl(mib, 4, buf, &len, NULL, 0); - if (error == -1) { - free_mem(buf, len1); - return (-UNW_EUNSPEC); - } - ret = -UNW_EUNSPEC; - for (bp = buf, eb = buf + len; bp < eb; bp += kv->kve_structsize) { - kv = (struct kinfo_vmentry *)(uintptr_t)bp; - if (ip < kv->kve_start || ip >= kv->kve_end) - continue; - if (kv->kve_type != KVME_TYPE_VNODE) - continue; - *segbase = kv->kve_start; - *mapoff = kv->kve_offset; - if (path) - { - strncpy(path, kv->kve_path, pathlen); - } - ret = elf_map_image (ei, kv->kve_path); - break; - } - free_mem(buf, len1); - return (ret); -} - -#ifndef UNW_REMOTE_ONLY - -PROTECTED void -tdep_get_exe_image_path (char *path) -{ - int mib[4], error; - size_t len; - - len = 0; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PATHNAME; - mib[3] = getpid(); - - error = sysctl(mib, 4, path, &len, NULL, 0); - if (error == -1) - path[0] = 0; -} - -#endif diff --git a/contrib/libunwind/src/os-hpux.c b/contrib/libunwind/src/os-hpux.c deleted file mode 100644 index d9435c1e6d6..00000000000 --- a/contrib/libunwind/src/os-hpux.c +++ /dev/null @@ -1,78 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include -#include - -#include "libunwind_i.h" - -#include "elf64.h" - -HIDDEN int -tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen) -{ - struct load_module_desc lmd; - const char *path2; - - if (pid != getpid ()) - { - printf ("%s: remote case not implemented yet\n", __FUNCTION__); - return -UNW_ENOINFO; - } - - if (!dlmodinfo (ip, &lmd, sizeof (lmd), NULL, 0, 0)) - return -UNW_ENOINFO; - - *segbase = lmd.text_base; - *mapoff = 0; /* XXX fix me? */ - - path2 = dlgetname (&lmd, sizeof (lmd), NULL, 0, 0); - if (!path2) - return -UNW_ENOINFO; - if (path) - { - strncpy(path, path2, pathlen); - path[pathlen - 1] = '\0'; - if (strcmp(path, path2) != 0) - Debug(1, "buffer size (%d) not big enough to hold path\n", pathlen); - } - Debug(1, "segbase=%lx, mapoff=%lx, path=%s\n", *segbase, *mapoff, path); - - return elf_map_image (ei, path); -} - -#ifndef UNW_REMOTE_ONLY - -PROTECTED void -tdep_get_exe_image_path (char *path) -{ - path[0] = 0; /* XXX */ -} - -#endif - diff --git a/contrib/libunwind/src/os-linux.c b/contrib/libunwind/src/os-linux.c deleted file mode 100644 index 25fe52af465..00000000000 --- a/contrib/libunwind/src/os-linux.c +++ /dev/null @@ -1,73 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "libunwind_i.h" -#include "os-linux.h" - -PROTECTED int -tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen) -{ - struct map_iterator mi; - int found = 0, rc; - unsigned long hi; - - if (maps_init (&mi, pid) < 0) - return -1; - - while (maps_next (&mi, segbase, &hi, mapoff)) - if (ip >= *segbase && ip < hi) - { - found = 1; - break; - } - - if (!found) - { - maps_close (&mi); - return -1; - } - if (path) - { - strncpy(path, mi.path, pathlen); - } - rc = elf_map_image (ei, mi.path); - maps_close (&mi); - return rc; -} - -#ifndef UNW_REMOTE_ONLY - -PROTECTED void -tdep_get_exe_image_path (char *path) -{ - strcpy(path, "/proc/self/exe"); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/os-linux.h b/contrib/libunwind/src/os-linux.h deleted file mode 100644 index 3976b38cc29..00000000000 --- a/contrib/libunwind/src/os-linux.h +++ /dev/null @@ -1,297 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Copyright (C) 2007 David Mosberger-Tang - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef os_linux_h -#define os_linux_h - -struct map_iterator - { - off_t offset; - int fd; - size_t buf_size; - char *buf; - char *buf_end; - char *path; - }; - -static inline char * -ltoa (char *buf, long val) -{ - char *cp = buf, tmp; - ssize_t i, len; - - do - { - *cp++ = '0' + (val % 10); - val /= 10; - } - while (val); - - /* reverse the order of the digits: */ - len = cp - buf; - --cp; - for (i = 0; i < len / 2; ++i) - { - tmp = buf[i]; - buf[i] = cp[-i]; - cp[-i] = tmp; - } - return buf + len; -} - -static inline int -maps_init (struct map_iterator *mi, pid_t pid) -{ - char path[sizeof ("/proc/0123456789/maps")], *cp; - - memcpy (path, "/proc/", 6); - cp = ltoa (path + 6, pid); - assert (cp + 6 < path + sizeof (path)); - memcpy (cp, "/maps", 6); - - mi->fd = open (path, O_RDONLY); - if (mi->fd >= 0) - { - /* Try to allocate a page-sized buffer. */ - mi->buf_size = getpagesize (); - cp = mmap (NULL, mi->buf_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (cp == MAP_FAILED) - { - close(mi->fd); - mi->fd = -1; - return -1; - } - else - { - mi->offset = 0; - mi->buf = mi->buf_end = cp + mi->buf_size; - return 0; - } - } - return -1; -} - -static inline char * -skip_whitespace (char *cp) -{ - if (!cp) - return NULL; - - while (*cp == ' ' || *cp == '\t') - ++cp; - return cp; -} - -static inline char * -scan_hex (char *cp, unsigned long *valp) -{ - unsigned long num_digits = 0, digit, val = 0; - - cp = skip_whitespace (cp); - if (!cp) - return NULL; - - while (1) - { - digit = *cp; - if ((digit - '0') <= 9) - digit -= '0'; - else if ((digit - 'a') < 6) - digit -= 'a' - 10; - else if ((digit - 'A') < 6) - digit -= 'A' - 10; - else - break; - val = (val << 4) | digit; - ++num_digits; - ++cp; - } - if (!num_digits) - return NULL; - *valp = val; - return cp; -} - -static inline char * -scan_dec (char *cp, unsigned long *valp) -{ - unsigned long num_digits = 0, digit, val = 0; - - if (!(cp = skip_whitespace (cp))) - return NULL; - - while (1) - { - digit = *cp; - if ((digit - '0') <= 9) - { - digit -= '0'; - ++cp; - } - else - break; - val = (10 * val) + digit; - ++num_digits; - } - if (!num_digits) - return NULL; - *valp = val; - return cp; -} - -static inline char * -scan_char (char *cp, char *valp) -{ - if (!cp) - return NULL; - - *valp = *cp; - - /* don't step over NUL terminator */ - if (*cp) - ++cp; - return cp; -} - -/* Scan a string delimited by white-space. Fails on empty string or - if string is doesn't fit in the specified buffer. */ -static inline char * -scan_string (char *cp, char *valp, size_t buf_size) -{ - size_t i = 0; - - if (!(cp = skip_whitespace (cp))) - return NULL; - - while (*cp != ' ' && *cp != '\t' && *cp != '\0') - { - if ((valp != NULL) && (i < buf_size - 1)) - valp[i++] = *cp; - ++cp; - } - if (i == 0 || i >= buf_size) - return NULL; - valp[i] = '\0'; - return cp; -} - -static inline int -maps_next (struct map_iterator *mi, - unsigned long *low, unsigned long *high, unsigned long *offset) -{ - char perm[16], dash = 0, colon = 0, *cp; - unsigned long major, minor, inum; - ssize_t i, nread; - - if (mi->fd < 0) - return 0; - - while (1) - { - ssize_t bytes_left = mi->buf_end - mi->buf; - char *eol = NULL; - - for (i = 0; i < bytes_left; ++i) - { - if (mi->buf[i] == '\n') - { - eol = mi->buf + i; - break; - } - else if (mi->buf[i] == '\0') - break; - } - if (!eol) - { - /* copy down the remaining bytes, if any */ - if (bytes_left > 0) - memmove (mi->buf_end - mi->buf_size, mi->buf, bytes_left); - - mi->buf = mi->buf_end - mi->buf_size; - nread = read (mi->fd, mi->buf + bytes_left, - mi->buf_size - bytes_left); - if (nread <= 0) - return 0; - else if ((size_t) (nread + bytes_left) < mi->buf_size) - { - /* Move contents to the end of the buffer so we - maintain the invariant that all bytes between - mi->buf and mi->buf_end are valid. */ - memmove (mi->buf_end - nread - bytes_left, mi->buf, - nread + bytes_left); - mi->buf = mi->buf_end - nread - bytes_left; - } - - eol = mi->buf + bytes_left + nread - 1; - - for (i = bytes_left; i < bytes_left + nread; ++i) - if (mi->buf[i] == '\n') - { - eol = mi->buf + i; - break; - } - } - cp = mi->buf; - mi->buf = eol + 1; - *eol = '\0'; - - /* scan: "LOW-HIGH PERM OFFSET MAJOR:MINOR INUM PATH" */ - cp = scan_hex (cp, low); - cp = scan_char (cp, &dash); - cp = scan_hex (cp, high); - cp = scan_string (cp, perm, sizeof (perm)); - cp = scan_hex (cp, offset); - cp = scan_hex (cp, &major); - cp = scan_char (cp, &colon); - cp = scan_hex (cp, &minor); - cp = scan_dec (cp, &inum); - cp = mi->path = skip_whitespace (cp); - if (!cp) - continue; - cp = scan_string (cp, NULL, 0); - if (dash != '-' || colon != ':') - continue; /* skip line with unknown or bad format */ - return 1; - } - return 0; -} - -static inline void -maps_close (struct map_iterator *mi) -{ - if (mi->fd < 0) - return; - close (mi->fd); - mi->fd = -1; - if (mi->buf) - { - munmap (mi->buf_end - mi->buf_size, mi->buf_size); - mi->buf = mi->buf_end = NULL; - } -} - -#endif /* os_linux_h */ diff --git a/contrib/libunwind/src/os-qnx.c b/contrib/libunwind/src/os-qnx.c deleted file mode 100644 index 4790992212f..00000000000 --- a/contrib/libunwind/src/os-qnx.c +++ /dev/null @@ -1,117 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2013 Garmin International - Contributed by Matt Fischer - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "libunwind_i.h" - -struct cb_info -{ - unw_word_t ip; - unsigned long segbase; - unsigned long offset; - const char *path; -}; - -static int callback(const struct dl_phdr_info *info, size_t size, void *data) -{ - int i; - struct cb_info *cbi = (struct cb_info*)data; - for(i=0; idlpi_phnum; i++) { - int segbase = info->dlpi_addr + info->dlpi_phdr[i].p_vaddr; - if(cbi->ip >= segbase && cbi->ip < segbase + info->dlpi_phdr[i].p_memsz) - { - cbi->path = info->dlpi_name; - cbi->offset = info->dlpi_phdr[i].p_offset; - cbi->segbase = segbase; - return 1; - } - } - - return 0; -} - -PROTECTED int -tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen) -{ - struct cb_info cbi; - int ret = -1; - cbi.ip = ip; - cbi.segbase = 0; - cbi.offset = 0; - cbi.path = NULL; - - /* QNX's support for accessing symbol maps is severely broken. There is - a devctl() call that can be made on a proc node (DCMD_PROC_MAPDEBUG) - which returns information similar to Linux's /proc//maps - node, however the filename that is returned by this call is not an - absolute path, and there is no foolproof way to map the filename - back to the file that it came from. - - Therefore, the normal approach for implementing this function, - which works equally well for both local and remote unwinding, - will not work here. The only type of image lookup which works - reliably is locally, using dl_iterate_phdr(). However, the only - time that this function is required to look up a remote image is for - ptrace support, which doesn't work on QNX anyway. Local unwinding, - which is the main case that makes use of this function, will work - fine with dl_iterate_phdr(). Therefore, in lieu of any better - platform support for remote image lookup, this function has just - been implemented in terms of dl_iterate_phdr(). - */ - - if (pid != getpid()) - { - /* Return an error if an attempt is made to perform remote image lookup */ - return -1; - } - - if (dl_iterate_phdr (callback, &cbi) != 0) - { - if (path) - { - strncpy (path, cbi.path, pathlen); - } - - *mapoff = cbi.offset; - *segbase = cbi.segbase; - - ret = elf_map_image (ei, cbi.path); - } - - return ret; -} - -#ifndef UNW_REMOTE_ONLY - -PROTECTED void -tdep_get_exe_image_path (char *path) -{ - path[0] = 0; /* XXX */ -} - -#endif diff --git a/contrib/libunwind/src/ppc/Gapply_reg_state.c b/contrib/libunwind/src/ppc/Gapply_reg_state.c deleted file mode 100644 index eec93046f56..00000000000 --- a/contrib/libunwind/src/ppc/Gapply_reg_state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); -} diff --git a/contrib/libunwind/src/ppc/Gget_proc_info.c b/contrib/libunwind/src/ppc/Gget_proc_info.c deleted file mode 100644 index 29f1db552ab..00000000000 --- a/contrib/libunwind/src/ppc/Gget_proc_info.c +++ /dev/null @@ -1,41 +0,0 @@ -/* libunwind - a platform-independent unwind library - - Copied from src/x86_64/, modified slightly (or made empty stubs) for - building frysk successfully on ppc64, by Wu Zhou - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -PROTECTED int -unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - ret = dwarf_make_proc_info (&c->dwarf); - if (ret < 0) - return ret; - - *pi = c->dwarf.pi; - return 0; -} diff --git a/contrib/libunwind/src/ppc/Gget_save_loc.c b/contrib/libunwind/src/ppc/Gget_save_loc.c deleted file mode 100644 index c5beb81d7d6..00000000000 --- a/contrib/libunwind/src/ppc/Gget_save_loc.c +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - - Copied from src/x86_64/, modified slightly (or made empty stubs) for - building frysk successfully on ppc64, by Wu Zhou - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -PROTECTED int -unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) -{ - /* XXX: empty stub. */ - return 0; -} diff --git a/contrib/libunwind/src/ppc/Ginit_local.c b/contrib/libunwind/src/ppc/Ginit_local.c deleted file mode 100644 index a05d4c8aaaa..00000000000 --- a/contrib/libunwind/src/ppc/Ginit_local.c +++ /dev/null @@ -1,88 +0,0 @@ -/* libunwind - a platform-independent unwind library - - Copied from src/x86_64/, modified slightly (or made empty stubs) for - building frysk successfully on ppc64, by Wu Zhou - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#ifdef UNW_TARGET_PPC64 -#include "../ppc64/init.h" -#else -#include "../ppc32/init.h" -#endif - -#ifdef UNW_REMOTE_ONLY - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - /* XXX: empty stub. */ - return -UNW_EINVAL; -} - -#else /* !UNW_REMOTE_ONLY */ - -static int -unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) -{ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = unw_local_addr_space; - c->dwarf.as_arg = uc; - #ifdef UNW_TARGET_PPC64 - return common_init_ppc64 (c, use_prev_instr); - #else - return common_init_ppc32 (c, use_prev_instr); - #endif -} - -PROTECTED int -unw_init_local(unw_cursor_t *cursor, ucontext_t *uc) -{ - return unw_init_local_common(cursor, uc, 1); -} - -PROTECTED int -unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) -{ - if (!flag) - { - return unw_init_local_common(cursor, uc, 1); - } - else if (flag == UNW_INIT_SIGNAL_FRAME) - { - return unw_init_local_common(cursor, uc, 0); - } - else - { - return -UNW_EINVAL; - } -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/ppc/Ginit_remote.c b/contrib/libunwind/src/ppc/Ginit_remote.c deleted file mode 100644 index 4ee54025a94..00000000000 --- a/contrib/libunwind/src/ppc/Ginit_remote.c +++ /dev/null @@ -1,60 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#ifdef UNW_TARGET_PPC64 -#include "../ppc64/init.h" -#else -#include "../ppc32/init.h" -#endif - -PROTECTED int -unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) -{ -#ifdef UNW_LOCAL_ONLY - return -UNW_EINVAL; -#else /* !UNW_LOCAL_ONLY */ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = as; - c->dwarf.as_arg = as_arg; - - #ifdef UNW_TARGET_PPC64 - return common_init_ppc64 (c, 0); - #elif UNW_TARGET_PPC32 - return common_init_ppc32 (c, 0); - #else - #error init_remote :: NO VALID PPC ARCH! - #endif -#endif /* !UNW_LOCAL_ONLY */ -} diff --git a/contrib/libunwind/src/ppc/Gis_signal_frame.c b/contrib/libunwind/src/ppc/Gis_signal_frame.c deleted file mode 100644 index e8b691781ef..00000000000 --- a/contrib/libunwind/src/ppc/Gis_signal_frame.c +++ /dev/null @@ -1,78 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -PROTECTED int -unw_is_signal_frame (unw_cursor_t * cursor) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, w1, i0, i1, i2, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - as->validate = 1; /* Don't trust the ip */ - arg = c->dwarf.as_arg; - - /* Check if return address points at sigreturn sequence. - on ppc64 Linux that is (see libc.so): - 0x38210080 addi r1, r1, 128 // pop the stack - 0x380000ac li r0, 172 // invoke system service 172 - 0x44000002 sc - */ - - ip = c->dwarf.ip; - if (ip == 0) - return 0; - - /* Read up two 8-byte words at the IP. We are only looking at 3 - consecutive 32-bit words, so the second 8-byte word needs to be - shifted right by 32 bits (think big-endian) */ - - a = unw_get_accessors (as); - if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 - || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0) - return 0; - - if (tdep_big_endian (as)) - { - i0 = w0 >> 32; - i1 = w0 & 0xffffffffUL; - i2 = w1 >> 32; - } - else - { - i0 = w0 & 0xffffffffUL; - i1 = w0 >> 32; - i2 = w1 & 0xffffffffUL; - } - - return (i0 == 0x38210080 && i1 == 0x380000ac && i2 == 0x44000002); -} diff --git a/contrib/libunwind/src/ppc/Greg_states_iterate.c b/contrib/libunwind/src/ppc/Greg_states_iterate.c deleted file mode 100644 index 99d967daebc..00000000000 --- a/contrib/libunwind/src/ppc/Greg_states_iterate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "../ppc64/unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_reg_states_iterate (&c->dwarf, cb, token); -} diff --git a/contrib/libunwind/src/ppc/Lapply_reg_state.c b/contrib/libunwind/src/ppc/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/ppc/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/ppc/Lget_proc_info.c b/contrib/libunwind/src/ppc/Lget_proc_info.c deleted file mode 100644 index 69028b019fc..00000000000 --- a/contrib/libunwind/src/ppc/Lget_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info.c" -#endif diff --git a/contrib/libunwind/src/ppc/Lget_save_loc.c b/contrib/libunwind/src/ppc/Lget_save_loc.c deleted file mode 100644 index 9ea048a9076..00000000000 --- a/contrib/libunwind/src/ppc/Lget_save_loc.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_save_loc.c" -#endif diff --git a/contrib/libunwind/src/ppc/Linit_local.c b/contrib/libunwind/src/ppc/Linit_local.c deleted file mode 100644 index 68a1687e854..00000000000 --- a/contrib/libunwind/src/ppc/Linit_local.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_local.c" -#endif diff --git a/contrib/libunwind/src/ppc/Linit_remote.c b/contrib/libunwind/src/ppc/Linit_remote.c deleted file mode 100644 index 58cb04ab7cd..00000000000 --- a/contrib/libunwind/src/ppc/Linit_remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_remote.c" -#endif diff --git a/contrib/libunwind/src/ppc/Lis_signal_frame.c b/contrib/libunwind/src/ppc/Lis_signal_frame.c deleted file mode 100644 index b9a7c4f51ad..00000000000 --- a/contrib/libunwind/src/ppc/Lis_signal_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gis_signal_frame.c" -#endif diff --git a/contrib/libunwind/src/ppc/Lreg_states_iterate.c b/contrib/libunwind/src/ppc/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/ppc/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/ppc/longjmp.S b/contrib/libunwind/src/ppc/longjmp.S deleted file mode 100644 index d363aef222f..00000000000 --- a/contrib/libunwind/src/ppc/longjmp.S +++ /dev/null @@ -1,36 +0,0 @@ -/* libunwind - a platform-independent unwind library - - Copied from src/x86_64/, modified slightly (or made empty stubs) for - building frysk successfully on ppc64, by Wu Zhou - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - - .globl _UI_longjmp_cont - - .type _UI_longjmp_cont, @function -_UI_longjmp_cont: - .size _UI_longjmp_cont, .-_UI_longjmp_cont - -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ppc/siglongjmp.S b/contrib/libunwind/src/ppc/siglongjmp.S deleted file mode 100644 index 64be36ce170..00000000000 --- a/contrib/libunwind/src/ppc/siglongjmp.S +++ /dev/null @@ -1,31 +0,0 @@ -/* libunwind - a platform-independent unwind library - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - - .globl _UI_siglongjmp_cont - - _UI_siglongjmp_cont: - -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ppc32/Gapply_reg_state.c b/contrib/libunwind/src/ppc32/Gapply_reg_state.c deleted file mode 100644 index eec93046f56..00000000000 --- a/contrib/libunwind/src/ppc32/Gapply_reg_state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); -} diff --git a/contrib/libunwind/src/ppc32/Gcreate_addr_space.c b/contrib/libunwind/src/ppc32/Gcreate_addr_space.c deleted file mode 100644 index f5055ecb982..00000000000 --- a/contrib/libunwind/src/ppc32/Gcreate_addr_space.c +++ /dev/null @@ -1,56 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* - * We support only big-endian on Linux ppc32. - */ - if (byte_order != 0 && byte_order != __BIG_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - return as; -#endif -} diff --git a/contrib/libunwind/src/ppc32/Gglobal.c b/contrib/libunwind/src/ppc32/Gglobal.c deleted file mode 100644 index a0f80beec6d..00000000000 --- a/contrib/libunwind/src/ppc32/Gglobal.c +++ /dev/null @@ -1,135 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "dwarf_i.h" - -HIDDEN define_lock (ppc32_lock); -HIDDEN int tdep_init_done; - -/* The API register numbers are exactly the same as the .eh_frame - registers, for now at least. */ -HIDDEN const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH] = - { - [UNW_PPC32_R0]=UNW_PPC32_R0, - [UNW_PPC32_R1]=UNW_PPC32_R1, - [UNW_PPC32_R2]=UNW_PPC32_R2, - [UNW_PPC32_R3]=UNW_PPC32_R3, - [UNW_PPC32_R4]=UNW_PPC32_R4, - [UNW_PPC32_R5]=UNW_PPC32_R5, - [UNW_PPC32_R6]=UNW_PPC32_R6, - [UNW_PPC32_R7]=UNW_PPC32_R7, - [UNW_PPC32_R8]=UNW_PPC32_R8, - [UNW_PPC32_R9]=UNW_PPC32_R9, - [UNW_PPC32_R10]=UNW_PPC32_R10, - [UNW_PPC32_R11]=UNW_PPC32_R11, - [UNW_PPC32_R12]=UNW_PPC32_R12, - [UNW_PPC32_R13]=UNW_PPC32_R13, - [UNW_PPC32_R14]=UNW_PPC32_R14, - [UNW_PPC32_R15]=UNW_PPC32_R15, - [UNW_PPC32_R16]=UNW_PPC32_R16, - [UNW_PPC32_R17]=UNW_PPC32_R17, - [UNW_PPC32_R18]=UNW_PPC32_R18, - [UNW_PPC32_R19]=UNW_PPC32_R19, - [UNW_PPC32_R20]=UNW_PPC32_R20, - [UNW_PPC32_R21]=UNW_PPC32_R21, - [UNW_PPC32_R22]=UNW_PPC32_R22, - [UNW_PPC32_R23]=UNW_PPC32_R23, - [UNW_PPC32_R24]=UNW_PPC32_R24, - [UNW_PPC32_R25]=UNW_PPC32_R25, - [UNW_PPC32_R26]=UNW_PPC32_R26, - [UNW_PPC32_R27]=UNW_PPC32_R27, - [UNW_PPC32_R28]=UNW_PPC32_R28, - [UNW_PPC32_R29]=UNW_PPC32_R29, - [UNW_PPC32_R30]=UNW_PPC32_R30, - [UNW_PPC32_R31]=UNW_PPC32_R31, - - [UNW_PPC32_CTR]=UNW_PPC32_CTR, - [UNW_PPC32_XER]=UNW_PPC32_XER, - [UNW_PPC32_CCR]=UNW_PPC32_CCR, - [UNW_PPC32_LR]=UNW_PPC32_LR, - [UNW_PPC32_FPSCR]=UNW_PPC32_FPSCR, - - [UNW_PPC32_F0]=UNW_PPC32_F0, - [UNW_PPC32_F1]=UNW_PPC32_F1, - [UNW_PPC32_F2]=UNW_PPC32_F2, - [UNW_PPC32_F3]=UNW_PPC32_F3, - [UNW_PPC32_F4]=UNW_PPC32_F4, - [UNW_PPC32_F5]=UNW_PPC32_F5, - [UNW_PPC32_F6]=UNW_PPC32_F6, - [UNW_PPC32_F7]=UNW_PPC32_F7, - [UNW_PPC32_F8]=UNW_PPC32_F8, - [UNW_PPC32_F9]=UNW_PPC32_F9, - [UNW_PPC32_F10]=UNW_PPC32_F10, - [UNW_PPC32_F11]=UNW_PPC32_F11, - [UNW_PPC32_F12]=UNW_PPC32_F12, - [UNW_PPC32_F13]=UNW_PPC32_F13, - [UNW_PPC32_F14]=UNW_PPC32_F14, - [UNW_PPC32_F15]=UNW_PPC32_F15, - [UNW_PPC32_F16]=UNW_PPC32_F16, - [UNW_PPC32_F17]=UNW_PPC32_F17, - [UNW_PPC32_F18]=UNW_PPC32_F18, - [UNW_PPC32_F19]=UNW_PPC32_F19, - [UNW_PPC32_F20]=UNW_PPC32_F20, - [UNW_PPC32_F21]=UNW_PPC32_F21, - [UNW_PPC32_F22]=UNW_PPC32_F22, - [UNW_PPC32_F23]=UNW_PPC32_F23, - [UNW_PPC32_F24]=UNW_PPC32_F24, - [UNW_PPC32_F25]=UNW_PPC32_F25, - [UNW_PPC32_F26]=UNW_PPC32_F26, - [UNW_PPC32_F27]=UNW_PPC32_F27, - [UNW_PPC32_F28]=UNW_PPC32_F28, - [UNW_PPC32_F29]=UNW_PPC32_F29, - [UNW_PPC32_F30]=UNW_PPC32_F30, - [UNW_PPC32_F31]=UNW_PPC32_F31, -}; - -HIDDEN void -tdep_init (void) -{ - intrmask_t saved_mask; - - sigfillset (&unwi_full_mask); - - lock_acquire (&ppc32_lock, saved_mask); - { - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - mi_init (); - - dwarf_init (); - -#ifndef UNW_REMOTE_ONLY - ppc32_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - } - out: - lock_release (&ppc32_lock, saved_mask); -} diff --git a/contrib/libunwind/src/ppc32/Ginit.c b/contrib/libunwind/src/ppc32/Ginit.c deleted file mode 100644 index dc599b9d0e4..00000000000 --- a/contrib/libunwind/src/ppc32/Ginit.c +++ /dev/null @@ -1,216 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "ucontext_i.h" -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -PROTECTED unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; - -static void * -uc_addr (ucontext_t *uc, int reg) -{ - void *addr; - - if ((unsigned) (reg - UNW_PPC32_R0) < 32) - addr = &uc->uc_mcontext.uc_regs->gregs[reg - UNW_PPC32_R0]; - - else - if ( ((unsigned) (reg - UNW_PPC32_F0) < 32) && - ((unsigned) (reg - UNW_PPC32_F0) >= 0) ) - addr = &uc->uc_mcontext.uc_regs->fpregs.fpregs[reg - UNW_PPC32_F0]; - - else - { - unsigned gregs_idx; - - switch (reg) - { - case UNW_PPC32_CTR: - gregs_idx = CTR_IDX; - break; - case UNW_PPC32_LR: - gregs_idx = LINK_IDX; - break; - case UNW_PPC32_XER: - gregs_idx = XER_IDX; - break; - case UNW_PPC32_CCR: - gregs_idx = CCR_IDX; - break; - default: - return NULL; - } - addr = &uc->uc_mcontext.uc_regs->gregs[gregs_idx]; - } - return addr; -} - -# ifdef UNW_LOCAL_ONLY - -HIDDEN void * -tdep_uc_addr (ucontext_t *uc, int reg) -{ - return uc_addr (uc, reg); -} - -# endif /* UNW_LOCAL_ONLY */ - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - - -static void -put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ - *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - if (write) - { - Debug (12, "mem[%lx] <- %lx\n", addr, *val); - *(unw_word_t *) addr = *val; - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "mem[%lx] -> %lx\n", addr, *val); - } - return 0; -} - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, - int write, void *arg) -{ - unw_word_t *addr; - ucontext_t *uc = arg; - - if ( ((unsigned int) (reg - UNW_PPC32_F0) < 32) && - ((unsigned int) (reg - UNW_PPC32_F0) >= 0)) - goto badreg; - - addr = uc_addr (uc, reg); - if (!addr) - goto badreg; - - if (write) - { - *(unw_word_t *) addr = *val; - Debug (12, "%s <- %lx\n", unw_regname (reg), *val); - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "%s -> %lx\n", unw_regname (reg), *val); - } - return 0; - -badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - ucontext_t *uc = arg; - unw_fpreg_t *addr; - - if ((unsigned) (reg - UNW_PPC32_F0) < 0) - goto badreg; - - addr = uc_addr (uc, reg); - if (!addr) - goto badreg; - - if (write) - { - Debug (12, "%s <- %016Lf\n", unw_regname (reg), *val); - *(unw_fpreg_t *) addr = *val; - } - else - { - *val = *(unw_fpreg_t *) addr; - Debug (12, "%s -> %016Lf\n", unw_regname (reg), *val); - } - return 0; - -badreg: - Debug (1, "bad register number %u\n", reg); - /* attempt to access a non-preserved register */ - return -UNW_EBADREG; -} - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp); -} - -HIDDEN void -ppc32_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; - local_addr_space.acc.find_proc_info = dwarf_find_proc_info; - local_addr_space.acc.put_unwind_info = put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = ppc32_local_resume; - local_addr_space.acc.get_proc_name = get_static_proc_name; - unw_flush_cache (&local_addr_space, 0, 0); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/ppc32/Greg_states_iterate.c b/contrib/libunwind/src/ppc32/Greg_states_iterate.c deleted file mode 100644 index a39837a1781..00000000000 --- a/contrib/libunwind/src/ppc32/Greg_states_iterate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_reg_states_iterate (&c->dwarf, cb, token); -} diff --git a/contrib/libunwind/src/ppc32/Gregs.c b/contrib/libunwind/src/ppc32/Gregs.c deleted file mode 100644 index 9344455e6cc..00000000000 --- a/contrib/libunwind/src/ppc32/Gregs.c +++ /dev/null @@ -1,90 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - struct dwarf_loc loc; - - switch (reg) - { - case UNW_TDEP_IP: - if (write) - { - c->dwarf.ip = *valp; /* update the IP cache */ - if (c->dwarf.pi_valid && (*valp < c->dwarf.pi.start_ip - || *valp >= c->dwarf.pi.end_ip)) - c->dwarf.pi_valid = 0; /* new IP outside of current proc */ - } - else - *valp = c->dwarf.ip; - return 0; - - case UNW_TDEP_SP: - if (write) - return -UNW_EREADONLYREG; - *valp = c->dwarf.cfa; - return 0; - - - default: - break; - } - - /* make sure it's not an FP or VR register */ - if ((((unsigned) (reg - UNW_PPC32_F0)) <= 31)) - return -UNW_EBADREG; - - loc = c->dwarf.loc[reg]; - - if (write) - return dwarf_put (&c->dwarf, loc, *valp); - else - return dwarf_get (&c->dwarf, loc, valp); -} - -HIDDEN int -tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, - int write) -{ - struct dwarf_loc loc; - - if ((unsigned) (reg - UNW_PPC32_F0) < 32) - { - loc = c->dwarf.loc[reg]; - if (write) - return dwarf_putfp (&c->dwarf, loc, *valp); - else - return dwarf_getfp (&c->dwarf, loc, valp); - } - - return -UNW_EBADREG; -} - diff --git a/contrib/libunwind/src/ppc32/Gresume.c b/contrib/libunwind/src/ppc32/Gresume.c deleted file mode 100644 index 955d061c6c4..00000000000 --- a/contrib/libunwind/src/ppc32/Gresume.c +++ /dev/null @@ -1,77 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford cjashfor@us.ibm.com - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -#ifndef UNW_REMOTE_ONLY - -#include - -/* sigreturn() is a no-op on x86_64 glibc. */ - -static NORETURN inline long -my_rt_sigreturn (void *new_sp) -{ - /* XXX: empty stub. */ - abort (); -} - -HIDDEN inline int -ppc32_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ - /* XXX: empty stub. */ - return -UNW_EINVAL; -} - -#endif /* !UNW_REMOTE_ONLY */ - -/* This routine is responsible for copying the register values in - cursor C and establishing them as the current machine state. */ - -static inline int -establish_machine_state (struct cursor *c) -{ - /* XXX: empty stub. */ - return 0; -} - -PROTECTED int -unw_resume (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - Debug (1, "(cursor=%p)\n", c); - - if ((ret = establish_machine_state (c)) < 0) - return ret; - - return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, - c->dwarf.as_arg); -} diff --git a/contrib/libunwind/src/ppc32/Gstep.c b/contrib/libunwind/src/ppc32/Gstep.c deleted file mode 100644 index 7e0f14d4d28..00000000000 --- a/contrib/libunwind/src/ppc32/Gstep.c +++ /dev/null @@ -1,309 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "ucontext_i.h" -#include - -/* This definition originates in /usr/include/asm-ppc64/ptrace.h, but is - defined there only when __KERNEL__ is defined. We reproduce it here for - our use at the user level in order to locate the ucontext record, which - appears to be at this offset relative to the stack pointer when in the - context of the signal handler return trampoline code - - __kernel_sigtramp_rt64. */ -#define __SIGNAL_FRAMESIZE 128 - -/* This definition comes from the document "64-bit PowerPC ELF Application - Binary Interface Supplement 1.9", section 3.2.2. - http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK */ - -typedef struct -{ - long unsigned back_chain; - long unsigned lr_save; - /* many more fields here, but they are unused by this code */ -} stack_frame_t; - - -PROTECTED int -unw_step (unw_cursor_t * cursor) -{ - struct cursor *c = (struct cursor *) cursor; - stack_frame_t dummy; - unw_word_t back_chain_offset, lr_save_offset; - struct dwarf_loc back_chain_loc, lr_save_loc, sp_loc, ip_loc; - int ret; - - Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->dwarf.ip); - - if (c->dwarf.ip == 0) - { - /* Unless the cursor or stack is corrupt or uninitialized, - we've most likely hit the top of the stack */ - return 0; - } - - /* Try DWARF-based unwinding... */ - - ret = dwarf_step (&c->dwarf); - - if (ret < 0 && ret != -UNW_ENOINFO) - { - Debug (2, "returning %d\n", ret); - return ret; - } - - if (unlikely (ret < 0)) - { - if (likely (unw_is_signal_frame (cursor) <= 0)) - { - /* DWARF unwinding failed. As of 09/26/2006, gcc in 64-bit mode - produces the mandatory level of traceback record in the code, but - I get the impression that this is transitory, that eventually gcc - will not produce any traceback records at all. So, for now, we - won't bother to try to find and use these records. - - We can, however, attempt to unwind the frame by using the callback - chain. This is very crude, however, and won't be able to unwind - any registers besides the IP, SP, and LR . */ - - back_chain_offset = ((void *) &dummy.back_chain - (void *) &dummy); - lr_save_offset = ((void *) &dummy.lr_save - (void *) &dummy); - - back_chain_loc = DWARF_LOC (c->dwarf.cfa + back_chain_offset, 0); - - if ((ret = - dwarf_get (&c->dwarf, back_chain_loc, &c->dwarf.cfa)) < 0) - { - Debug (2, - "Unable to retrieve CFA from back chain in stack frame - %d\n", - ret); - return ret; - } - if (c->dwarf.cfa == 0) - /* Unless the cursor or stack is corrupt or uninitialized we've most - likely hit the top of the stack */ - return 0; - - lr_save_loc = DWARF_LOC (c->dwarf.cfa + lr_save_offset, 0); - - if ((ret = dwarf_get (&c->dwarf, lr_save_loc, &c->dwarf.ip)) < 0) - { - Debug (2, - "Unable to retrieve IP from lr save in stack frame - %d\n", - ret); - return ret; - } - ret = 1; - } - else - { - /* Find the sigcontext record by taking the CFA and adjusting by - the dummy signal frame size. - - Note that there isn't any way to determined if SA_SIGINFO was - set in the sa_flags parameter to sigaction when the signal - handler was established. If it was not set, the ucontext - record is not required to be on the stack, in which case the - following code will likely cause a seg fault or other crash - condition. */ - - unw_word_t ucontext = c->dwarf.cfa + __SIGNAL_FRAMESIZE; - - Debug (1, "signal frame, skip over trampoline\n"); - - c->sigcontext_format = PPC_SCF_LINUX_RT_SIGFRAME; - c->sigcontext_addr = ucontext; - - sp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0); - ip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0); - - ret = dwarf_get (&c->dwarf, sp_loc, &c->dwarf.cfa); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - ret = dwarf_get (&c->dwarf, ip_loc, &c->dwarf.ip); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - - /* Instead of just restoring the non-volatile registers, do all - of the registers for now. This will incur a performance hit, - but it's rare enough not to cause too much of a problem, and - might be useful in some cases. */ - c->dwarf.loc[UNW_PPC32_R0] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R0, 0); - c->dwarf.loc[UNW_PPC32_R1] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0); - c->dwarf.loc[UNW_PPC32_R2] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R2, 0); - c->dwarf.loc[UNW_PPC32_R3] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R3, 0); - c->dwarf.loc[UNW_PPC32_R4] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R4, 0); - c->dwarf.loc[UNW_PPC32_R5] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R5, 0); - c->dwarf.loc[UNW_PPC32_R6] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R6, 0); - c->dwarf.loc[UNW_PPC32_R7] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R7, 0); - c->dwarf.loc[UNW_PPC32_R8] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); - c->dwarf.loc[UNW_PPC32_R9] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); - c->dwarf.loc[UNW_PPC32_R10] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); - c->dwarf.loc[UNW_PPC32_R11] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); - c->dwarf.loc[UNW_PPC32_R12] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); - c->dwarf.loc[UNW_PPC32_R13] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); - c->dwarf.loc[UNW_PPC32_R14] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); - c->dwarf.loc[UNW_PPC32_R15] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); - c->dwarf.loc[UNW_PPC32_R16] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R16, 0); - c->dwarf.loc[UNW_PPC32_R17] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R17, 0); - c->dwarf.loc[UNW_PPC32_R18] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R18, 0); - c->dwarf.loc[UNW_PPC32_R19] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R19, 0); - c->dwarf.loc[UNW_PPC32_R20] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R20, 0); - c->dwarf.loc[UNW_PPC32_R21] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R21, 0); - c->dwarf.loc[UNW_PPC32_R22] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R22, 0); - c->dwarf.loc[UNW_PPC32_R23] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R23, 0); - c->dwarf.loc[UNW_PPC32_R24] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R24, 0); - c->dwarf.loc[UNW_PPC32_R25] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R25, 0); - c->dwarf.loc[UNW_PPC32_R26] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R26, 0); - c->dwarf.loc[UNW_PPC32_R27] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R27, 0); - c->dwarf.loc[UNW_PPC32_R28] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R28, 0); - c->dwarf.loc[UNW_PPC32_R29] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R29, 0); - c->dwarf.loc[UNW_PPC32_R30] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R30, 0); - c->dwarf.loc[UNW_PPC32_R31] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R31, 0); - - c->dwarf.loc[UNW_PPC32_LR] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0); - c->dwarf.loc[UNW_PPC32_CTR] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CTR, 0); - - /* This CR0 assignment is probably wrong. There are 8 dwarf columns - assigned to the CR registers, but only one CR register in the - mcontext structure */ - c->dwarf.loc[UNW_PPC32_CCR] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CCR, 0); - c->dwarf.loc[UNW_PPC32_XER] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_XER, 0); - - c->dwarf.loc[UNW_PPC32_F0] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R0, 0); - c->dwarf.loc[UNW_PPC32_F1] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R1, 0); - c->dwarf.loc[UNW_PPC32_F2] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R2, 0); - c->dwarf.loc[UNW_PPC32_F3] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R3, 0); - c->dwarf.loc[UNW_PPC32_F4] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R4, 0); - c->dwarf.loc[UNW_PPC32_F5] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R5, 0); - c->dwarf.loc[UNW_PPC32_F6] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R6, 0); - c->dwarf.loc[UNW_PPC32_F7] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R7, 0); - c->dwarf.loc[UNW_PPC32_F8] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R8, 0); - c->dwarf.loc[UNW_PPC32_F9] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R9, 0); - c->dwarf.loc[UNW_PPC32_F10] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R10, 0); - c->dwarf.loc[UNW_PPC32_F11] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R11, 0); - c->dwarf.loc[UNW_PPC32_F12] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R12, 0); - c->dwarf.loc[UNW_PPC32_F13] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R13, 0); - c->dwarf.loc[UNW_PPC32_F14] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R14, 0); - c->dwarf.loc[UNW_PPC32_F15] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R15, 0); - c->dwarf.loc[UNW_PPC32_F16] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R16, 0); - c->dwarf.loc[UNW_PPC32_F17] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R17, 0); - c->dwarf.loc[UNW_PPC32_F18] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R18, 0); - c->dwarf.loc[UNW_PPC32_F19] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R19, 0); - c->dwarf.loc[UNW_PPC32_F20] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R20, 0); - c->dwarf.loc[UNW_PPC32_F21] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R21, 0); - c->dwarf.loc[UNW_PPC32_F22] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R22, 0); - c->dwarf.loc[UNW_PPC32_F23] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R23, 0); - c->dwarf.loc[UNW_PPC32_F24] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R24, 0); - c->dwarf.loc[UNW_PPC32_F25] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R25, 0); - c->dwarf.loc[UNW_PPC32_F26] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R26, 0); - c->dwarf.loc[UNW_PPC32_F27] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R27, 0); - c->dwarf.loc[UNW_PPC32_F28] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R28, 0); - c->dwarf.loc[UNW_PPC32_F29] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R29, 0); - c->dwarf.loc[UNW_PPC32_F30] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R30, 0); - c->dwarf.loc[UNW_PPC32_F31] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R31, 0); - - ret = 1; - } - } - return ret; -} diff --git a/contrib/libunwind/src/ppc32/Lapply_reg_state.c b/contrib/libunwind/src/ppc32/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/ppc32/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/ppc32/Lcreate_addr_space.c b/contrib/libunwind/src/ppc32/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901..00000000000 --- a/contrib/libunwind/src/ppc32/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/contrib/libunwind/src/ppc32/Lglobal.c b/contrib/libunwind/src/ppc32/Lglobal.c deleted file mode 100644 index 6d7b489e14b..00000000000 --- a/contrib/libunwind/src/ppc32/Lglobal.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/contrib/libunwind/src/ppc32/Linit.c b/contrib/libunwind/src/ppc32/Linit.c deleted file mode 100644 index e9abfdd46a3..00000000000 --- a/contrib/libunwind/src/ppc32/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/contrib/libunwind/src/ppc32/Lreg_states_iterate.c b/contrib/libunwind/src/ppc32/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/ppc32/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/ppc32/Lregs.c b/contrib/libunwind/src/ppc32/Lregs.c deleted file mode 100644 index 2c9c75cd7d9..00000000000 --- a/contrib/libunwind/src/ppc32/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/contrib/libunwind/src/ppc32/Lresume.c b/contrib/libunwind/src/ppc32/Lresume.c deleted file mode 100644 index 41a8cf003de..00000000000 --- a/contrib/libunwind/src/ppc32/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/contrib/libunwind/src/ppc32/Lstep.c b/contrib/libunwind/src/ppc32/Lstep.c deleted file mode 100644 index c1ac3c7547f..00000000000 --- a/contrib/libunwind/src/ppc32/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/contrib/libunwind/src/ppc32/Make-arch.in b/contrib/libunwind/src/ppc32/Make-arch.in deleted file mode 100644 index 947dd5fa03d..00000000000 --- a/contrib/libunwind/src/ppc32/Make-arch.in +++ /dev/null @@ -1,11 +0,0 @@ -# Word size. -ELFW = 64 -# Does use dwarf2 unwind info. -dwarf_target = true - -libunwind_setjmp_OBJS += \ - $(arch)/longjmp.o \ - $(arch)/siglongjmp.o - -libunwind_OBJS_common += \ - $(arch)/is_fpreg.o diff --git a/contrib/libunwind/src/ppc32/get_func_addr.c b/contrib/libunwind/src/ppc32/get_func_addr.c deleted file mode 100644 index 66ff795fe7e..00000000000 --- a/contrib/libunwind/src/ppc32/get_func_addr.c +++ /dev/null @@ -1,36 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -int -tdep_get_func_addr (unw_addr_space_t as, unw_word_t symbol_val_addr, - unw_word_t *real_func_addr) -{ - *real_func_addr = symbol_val_addr; - return 0; -} diff --git a/contrib/libunwind/src/ppc32/init.h b/contrib/libunwind/src/ppc32/init.h deleted file mode 100644 index 87a69b1450a..00000000000 --- a/contrib/libunwind/src/ppc32/init.h +++ /dev/null @@ -1,72 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -/* Here is the "common" init, for remote and local debuging" */ - -static inline int -common_init_ppc32 (struct cursor *c, unsigned use_prev_instr) -{ - int ret; - int i; - - for (i = UNW_PPC32_R0; i <= UNW_PPC32_R31; i++) { - c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, i); - } - for (i = UNW_PPC32_F0; i <= UNW_PPC32_F31; i++) { - c->dwarf.loc[i] = DWARF_FPREG_LOC (&c->dwarf, i); - } - - c->dwarf.loc[UNW_PPC32_CTR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_CTR); - c->dwarf.loc[UNW_PPC32_XER] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_XER); - c->dwarf.loc[UNW_PPC32_CCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_CCR); - c->dwarf.loc[UNW_PPC32_LR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_LR); - c->dwarf.loc[UNW_PPC32_FPSCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC32_FPSCR); - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_PPC32_LR], &c->dwarf.ip); - if (ret < 0) - return ret; - - ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_PPC32_R1), - &c->dwarf.cfa); - if (ret < 0) - return ret; - - c->sigcontext_format = PPC_SCF_NONE; - c->sigcontext_addr = 0; - - c->dwarf.args_size = 0; - c->dwarf.stash_frames = 0; - c->dwarf.use_prev_instr = use_prev_instr; - c->dwarf.pi_valid = 0; - c->dwarf.pi_is_dynamic = 0; - c->dwarf.hint = 0; - c->dwarf.prev_rs = 0; - - return 0; -} diff --git a/contrib/libunwind/src/ppc32/is_fpreg.c b/contrib/libunwind/src/ppc32/is_fpreg.c deleted file mode 100644 index cccc5112bc1..00000000000 --- a/contrib/libunwind/src/ppc32/is_fpreg.c +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_is_fpreg (int regnum) -{ - return (regnum >= UNW_PPC32_F0 && regnum <= UNW_PPC32_F31); -} diff --git a/contrib/libunwind/src/ppc32/regname.c b/contrib/libunwind/src/ppc32/regname.c deleted file mode 100644 index 79ba88aa56f..00000000000 --- a/contrib/libunwind/src/ppc32/regname.c +++ /dev/null @@ -1,112 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static const char *regname[] = - { - [UNW_PPC32_R0]="GPR0", - [UNW_PPC32_R1]="GPR1", - [UNW_PPC32_R2]="GPR2", - [UNW_PPC32_R3]="GPR3", - [UNW_PPC32_R4]="GPR4", - [UNW_PPC32_R5]="GPR5", - [UNW_PPC32_R6]="GPR6", - [UNW_PPC32_R7]="GPR7", - [UNW_PPC32_R8]="GPR8", - [UNW_PPC32_R9]="GPR9", - [UNW_PPC32_R10]="GPR10", - [UNW_PPC32_R11]="GPR11", - [UNW_PPC32_R12]="GPR12", - [UNW_PPC32_R13]="GPR13", - [UNW_PPC32_R14]="GPR14", - [UNW_PPC32_R15]="GPR15", - [UNW_PPC32_R16]="GPR16", - [UNW_PPC32_R17]="GPR17", - [UNW_PPC32_R18]="GPR18", - [UNW_PPC32_R19]="GPR19", - [UNW_PPC32_R20]="GPR20", - [UNW_PPC32_R21]="GPR21", - [UNW_PPC32_R22]="GPR22", - [UNW_PPC32_R23]="GPR23", - [UNW_PPC32_R24]="GPR24", - [UNW_PPC32_R25]="GPR25", - [UNW_PPC32_R26]="GPR26", - [UNW_PPC32_R27]="GPR27", - [UNW_PPC32_R28]="GPR28", - [UNW_PPC32_R29]="GPR29", - [UNW_PPC32_R30]="GPR30", - [UNW_PPC32_R31]="GPR31", - - [UNW_PPC32_CTR]="CTR", - [UNW_PPC32_XER]="XER", - [UNW_PPC32_CCR]="CCR", - [UNW_PPC32_LR]="LR", - [UNW_PPC32_FPSCR]="FPSCR", - - [UNW_PPC32_F0]="FPR0", - [UNW_PPC32_F1]="FPR1", - [UNW_PPC32_F2]="FPR2", - [UNW_PPC32_F3]="FPR3", - [UNW_PPC32_F4]="FPR4", - [UNW_PPC32_F5]="FPR5", - [UNW_PPC32_F6]="FPR6", - [UNW_PPC32_F7]="FPR7", - [UNW_PPC32_F8]="FPR8", - [UNW_PPC32_F9]="FPR9", - [UNW_PPC32_F10]="FPR10", - [UNW_PPC32_F11]="FPR11", - [UNW_PPC32_F12]="FPR12", - [UNW_PPC32_F13]="FPR13", - [UNW_PPC32_F14]="FPR14", - [UNW_PPC32_F15]="FPR15", - [UNW_PPC32_F16]="FPR16", - [UNW_PPC32_F17]="FPR17", - [UNW_PPC32_F18]="FPR18", - [UNW_PPC32_F19]="FPR19", - [UNW_PPC32_F20]="FPR20", - [UNW_PPC32_F21]="FPR21", - [UNW_PPC32_F22]="FPR22", - [UNW_PPC32_F23]="FPR23", - [UNW_PPC32_F24]="FPR24", - [UNW_PPC32_F25]="FPR25", - [UNW_PPC32_F26]="FPR26", - [UNW_PPC32_F27]="FPR27", - [UNW_PPC32_F28]="FPR28", - [UNW_PPC32_F29]="FPR29", - [UNW_PPC32_F30]="FPR30", - [UNW_PPC32_F31]="FPR31" -}; - -PROTECTED const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) - return regname[reg]; - else - return "???"; -} diff --git a/contrib/libunwind/src/ppc32/setcontext.S b/contrib/libunwind/src/ppc32/setcontext.S deleted file mode 100644 index b54378a9dc2..00000000000 --- a/contrib/libunwind/src/ppc32/setcontext.S +++ /dev/null @@ -1,9 +0,0 @@ - .global _UI_setcontext - -_UI_setcontext: - retq - -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ppc32/ucontext_i.h b/contrib/libunwind/src/ppc32/ucontext_i.h deleted file mode 100644 index c6ba806a00c..00000000000 --- a/contrib/libunwind/src/ppc32/ucontext_i.h +++ /dev/null @@ -1,128 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef ucontext_i_h -#define ucontext_i_h - -#include "compiler.h" -#include - -/* These values were derived by reading - /usr/src/linux-2.6.18-1.8/arch/um/include/sysdep-ppc/ptrace.h and - /usr/src/linux-2.6.18-1.8/arch/powerpc/kernel/ppc32.h -*/ - -//#define NIP_IDX 32 -#define CTR_IDX 32 -#define XER_IDX 33 -#define CCR_IDX 34 -#define MSR_IDX 35 -//#define MQ_IDX 36 -#define LINK_IDX 36 - -/* These are dummy structures used only for obtaining the offsets of the - various structure members. */ -static ucontext_t dmy_ctxt UNUSED; - -#define UC_MCONTEXT_GREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[0] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[1] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[2] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[3] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[4] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[5] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[6] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[7] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[8] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[9] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[10] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[11] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[12] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[13] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[14] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[15] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[16] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[17] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[18] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[19] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[20] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[21] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[22] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[23] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[24] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[25] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[26] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[27] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[28] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[29] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[30] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[31] - (void *)&dmy_ctxt) - -#define UC_MCONTEXT_GREGS_MSR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[MSR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_ORIG_GPR3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[ORIG_GPR3_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_CTR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[CTR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_LINK ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[LINK_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_XER ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[XER_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_CCR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[CCR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_SOFTE ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[SOFTE_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_TRAP ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[TRAP_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_DAR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[DAR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_DSISR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[DSISR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_RESULT ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[RESULT_IDX] - (void *)&dmy_ctxt) - -#define UC_MCONTEXT_FREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[0] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[1] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[2] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[3] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[4] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[5] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[6] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[7] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[8] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[9] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[10] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[11] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[12] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[13] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[14] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[15] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[16] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[17] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[18] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[19] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[20] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[21] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[22] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[23] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[24] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[25] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[26] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[27] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[28] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[29] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[30] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[31] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_FPSCR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[32] - (void *)&dmy_ctxt) - -#endif diff --git a/contrib/libunwind/src/ppc32/unwind_i.h b/contrib/libunwind/src/ppc32/unwind_i.h deleted file mode 100644 index ad32d056544..00000000000 --- a/contrib/libunwind/src/ppc32/unwind_i.h +++ /dev/null @@ -1,46 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include - -#include - -#include -#include - -#define ppc32_lock UNW_OBJ(lock) -#define ppc32_local_resume UNW_OBJ(local_resume) -#define ppc32_local_addr_space_init UNW_OBJ(local_addr_space_init) - -extern void ppc32_local_addr_space_init (void); -extern int ppc32_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, - void *arg); - -#endif /* unwind_i_h */ diff --git a/contrib/libunwind/src/ppc64/Gapply_reg_state.c b/contrib/libunwind/src/ppc64/Gapply_reg_state.c deleted file mode 100644 index eec93046f56..00000000000 --- a/contrib/libunwind/src/ppc64/Gapply_reg_state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); -} diff --git a/contrib/libunwind/src/ppc64/Gcreate_addr_space.c b/contrib/libunwind/src/ppc64/Gcreate_addr_space.c deleted file mode 100644 index 686653a96e6..00000000000 --- a/contrib/libunwind/src/ppc64/Gcreate_addr_space.c +++ /dev/null @@ -1,71 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* - * We support both big- and little-endian on Linux ppc64. - */ - if (byte_order != 0 - && byte_order != __LITTLE_ENDIAN - && byte_order != __BIG_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - if (byte_order == 0) - /* use host default: */ - as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); - else - as->big_endian = (byte_order == __BIG_ENDIAN); - - /* FIXME! There is no way to specify the ABI. - Default to ELFv1 on big-endian and ELFv2 on little-endian. */ - if (as->big_endian) - as->abi = UNW_PPC64_ABI_ELFv1; - else - as->abi = UNW_PPC64_ABI_ELFv2; - - return as; -#endif -} diff --git a/contrib/libunwind/src/ppc64/Gglobal.c b/contrib/libunwind/src/ppc64/Gglobal.c deleted file mode 100644 index 9d0b0f55a6c..00000000000 --- a/contrib/libunwind/src/ppc64/Gglobal.c +++ /dev/null @@ -1,182 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "dwarf_i.h" - -HIDDEN define_lock (ppc64_lock); -HIDDEN int tdep_init_done; - -/* The API register numbers are exactly the same as the .eh_frame - registers, for now at least. */ -HIDDEN const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH] = - { - [UNW_PPC64_R0]=UNW_PPC64_R0, - [UNW_PPC64_R1]=UNW_PPC64_R1, - [UNW_PPC64_R2]=UNW_PPC64_R2, - [UNW_PPC64_R3]=UNW_PPC64_R3, - [UNW_PPC64_R4]=UNW_PPC64_R4, - [UNW_PPC64_R5]=UNW_PPC64_R5, - [UNW_PPC64_R6]=UNW_PPC64_R6, - [UNW_PPC64_R7]=UNW_PPC64_R7, - [UNW_PPC64_R8]=UNW_PPC64_R8, - [UNW_PPC64_R9]=UNW_PPC64_R9, - [UNW_PPC64_R10]=UNW_PPC64_R10, - [UNW_PPC64_R11]=UNW_PPC64_R11, - [UNW_PPC64_R12]=UNW_PPC64_R12, - [UNW_PPC64_R13]=UNW_PPC64_R13, - [UNW_PPC64_R14]=UNW_PPC64_R14, - [UNW_PPC64_R15]=UNW_PPC64_R15, - [UNW_PPC64_R16]=UNW_PPC64_R16, - [UNW_PPC64_R17]=UNW_PPC64_R17, - [UNW_PPC64_R18]=UNW_PPC64_R18, - [UNW_PPC64_R19]=UNW_PPC64_R19, - [UNW_PPC64_R20]=UNW_PPC64_R20, - [UNW_PPC64_R21]=UNW_PPC64_R21, - [UNW_PPC64_R22]=UNW_PPC64_R22, - [UNW_PPC64_R23]=UNW_PPC64_R23, - [UNW_PPC64_R24]=UNW_PPC64_R24, - [UNW_PPC64_R25]=UNW_PPC64_R25, - [UNW_PPC64_R26]=UNW_PPC64_R26, - [UNW_PPC64_R27]=UNW_PPC64_R27, - [UNW_PPC64_R28]=UNW_PPC64_R28, - [UNW_PPC64_R29]=UNW_PPC64_R29, - [UNW_PPC64_R30]=UNW_PPC64_R30, - [UNW_PPC64_R31]=UNW_PPC64_R31, - - [UNW_PPC64_F0]=UNW_PPC64_F0, - [UNW_PPC64_F1]=UNW_PPC64_F1, - [UNW_PPC64_F2]=UNW_PPC64_F2, - [UNW_PPC64_F3]=UNW_PPC64_F3, - [UNW_PPC64_F4]=UNW_PPC64_F4, - [UNW_PPC64_F5]=UNW_PPC64_F5, - [UNW_PPC64_F6]=UNW_PPC64_F6, - [UNW_PPC64_F7]=UNW_PPC64_F7, - [UNW_PPC64_F8]=UNW_PPC64_F8, - [UNW_PPC64_F9]=UNW_PPC64_F9, - [UNW_PPC64_F10]=UNW_PPC64_F10, - [UNW_PPC64_F11]=UNW_PPC64_F11, - [UNW_PPC64_F12]=UNW_PPC64_F12, - [UNW_PPC64_F13]=UNW_PPC64_F13, - [UNW_PPC64_F14]=UNW_PPC64_F14, - [UNW_PPC64_F15]=UNW_PPC64_F15, - [UNW_PPC64_F16]=UNW_PPC64_F16, - [UNW_PPC64_F17]=UNW_PPC64_F17, - [UNW_PPC64_F18]=UNW_PPC64_F18, - [UNW_PPC64_F19]=UNW_PPC64_F19, - [UNW_PPC64_F20]=UNW_PPC64_F20, - [UNW_PPC64_F21]=UNW_PPC64_F21, - [UNW_PPC64_F22]=UNW_PPC64_F22, - [UNW_PPC64_F23]=UNW_PPC64_F23, - [UNW_PPC64_F24]=UNW_PPC64_F24, - [UNW_PPC64_F25]=UNW_PPC64_F25, - [UNW_PPC64_F26]=UNW_PPC64_F26, - [UNW_PPC64_F27]=UNW_PPC64_F27, - [UNW_PPC64_F28]=UNW_PPC64_F28, - [UNW_PPC64_F29]=UNW_PPC64_F29, - [UNW_PPC64_F30]=UNW_PPC64_F30, - [UNW_PPC64_F31]=UNW_PPC64_F31, - - [UNW_PPC64_LR]=UNW_PPC64_LR, - [UNW_PPC64_CTR]=UNW_PPC64_CTR, - [UNW_PPC64_ARG_POINTER]=UNW_PPC64_ARG_POINTER, - - [UNW_PPC64_CR0]=UNW_PPC64_CR0, - [UNW_PPC64_CR1]=UNW_PPC64_CR1, - [UNW_PPC64_CR2]=UNW_PPC64_CR2, - [UNW_PPC64_CR3]=UNW_PPC64_CR3, - [UNW_PPC64_CR4]=UNW_PPC64_CR4, - [UNW_PPC64_CR5]=UNW_PPC64_CR5, - [UNW_PPC64_CR6]=UNW_PPC64_CR6, - [UNW_PPC64_CR7]=UNW_PPC64_CR7, - - [UNW_PPC64_XER]=UNW_PPC64_XER, - - [UNW_PPC64_V0]=UNW_PPC64_V0, - [UNW_PPC64_V1]=UNW_PPC64_V1, - [UNW_PPC64_V2]=UNW_PPC64_V2, - [UNW_PPC64_V3]=UNW_PPC64_V3, - [UNW_PPC64_V4]=UNW_PPC64_V4, - [UNW_PPC64_V5]=UNW_PPC64_V5, - [UNW_PPC64_V6]=UNW_PPC64_V6, - [UNW_PPC64_V7]=UNW_PPC64_V7, - [UNW_PPC64_V8]=UNW_PPC64_V8, - [UNW_PPC64_V9]=UNW_PPC64_V9, - [UNW_PPC64_V10]=UNW_PPC64_V10, - [UNW_PPC64_V11]=UNW_PPC64_V11, - [UNW_PPC64_V12]=UNW_PPC64_V12, - [UNW_PPC64_V13]=UNW_PPC64_V13, - [UNW_PPC64_V14]=UNW_PPC64_V14, - [UNW_PPC64_V15]=UNW_PPC64_V15, - [UNW_PPC64_V16]=UNW_PPC64_V16, - [UNW_PPC64_V17]=UNW_PPC64_V17, - [UNW_PPC64_V18]=UNW_PPC64_V18, - [UNW_PPC64_V19]=UNW_PPC64_V19, - [UNW_PPC64_V20]=UNW_PPC64_V20, - [UNW_PPC64_V21]=UNW_PPC64_V21, - [UNW_PPC64_V22]=UNW_PPC64_V22, - [UNW_PPC64_V23]=UNW_PPC64_V23, - [UNW_PPC64_V24]=UNW_PPC64_V24, - [UNW_PPC64_V25]=UNW_PPC64_V25, - [UNW_PPC64_V26]=UNW_PPC64_V26, - [UNW_PPC64_V27]=UNW_PPC64_V27, - [UNW_PPC64_V28]=UNW_PPC64_V28, - [UNW_PPC64_V29]=UNW_PPC64_V29, - [UNW_PPC64_V30]=UNW_PPC64_V30, - [UNW_PPC64_V31]=UNW_PPC64_V31, - - [UNW_PPC64_VRSAVE]=UNW_PPC64_VRSAVE, - [UNW_PPC64_VSCR]=UNW_PPC64_VSCR, - [UNW_PPC64_SPE_ACC]=UNW_PPC64_SPE_ACC, - [UNW_PPC64_SPEFSCR]=UNW_PPC64_SPEFSCR, - }; - -HIDDEN void -tdep_init (void) -{ - intrmask_t saved_mask; - - sigfillset (&unwi_full_mask); - - lock_acquire (&ppc64_lock, saved_mask); - { - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - mi_init (); - - dwarf_init (); - -#ifndef UNW_REMOTE_ONLY - ppc64_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - } - out: - lock_release (&ppc64_lock, saved_mask); -} diff --git a/contrib/libunwind/src/ppc64/Ginit.c b/contrib/libunwind/src/ppc64/Ginit.c deleted file mode 100644 index 287ecf4923d..00000000000 --- a/contrib/libunwind/src/ppc64/Ginit.c +++ /dev/null @@ -1,229 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "ucontext_i.h" -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -PROTECTED unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; - -static void * -uc_addr (ucontext_t *uc, int reg) -{ - void *addr; - - if ((unsigned) (reg - UNW_PPC64_R0) < 32) - addr = &uc->uc_mcontext.gp_regs[reg - UNW_PPC64_R0]; - - else if ((unsigned) (reg - UNW_PPC64_F0) < 32) - addr = &uc->uc_mcontext.fp_regs[reg - UNW_PPC64_F0]; - - else if ((unsigned) (reg - UNW_PPC64_V0) < 32) - addr = (uc->uc_mcontext.v_regs == 0) ? NULL : &uc->uc_mcontext.v_regs->vrregs[reg - UNW_PPC64_V0][0]; - - else - { - unsigned gregs_idx; - - switch (reg) - { - case UNW_PPC64_NIP: - gregs_idx = NIP_IDX; - break; - case UNW_PPC64_CTR: - gregs_idx = CTR_IDX; - break; - case UNW_PPC64_LR: - gregs_idx = LINK_IDX; - break; - case UNW_PPC64_XER: - gregs_idx = XER_IDX; - break; - case UNW_PPC64_CR0: - gregs_idx = CCR_IDX; - break; - default: - return NULL; - } - addr = &uc->uc_mcontext.gp_regs[gregs_idx]; - } - return addr; -} - -# ifdef UNW_LOCAL_ONLY - -HIDDEN void * -tdep_uc_addr (ucontext_t *uc, int reg) -{ - return uc_addr (uc, reg); -} - -# endif /* UNW_LOCAL_ONLY */ - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - - -static void -put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ - *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - if (write) - { - Debug (12, "mem[%lx] <- %lx\n", addr, *val); - *(unw_word_t *) addr = *val; - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "mem[%lx] -> %lx\n", addr, *val); - } - return 0; -} - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, - int write, void *arg) -{ - unw_word_t *addr; - ucontext_t *uc = arg; - - if (UNW_PPC64_F0 <= reg && reg <= UNW_PPC64_F31) - goto badreg; - if (UNW_PPC64_V0 <= reg && reg <= UNW_PPC64_V31) - goto badreg; - - addr = uc_addr (uc, reg); - if (!addr) - goto badreg; - - if (write) - { - *(unw_word_t *) addr = *val; - Debug (12, "%s <- %lx\n", unw_regname (reg), *val); - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "%s -> %lx\n", unw_regname (reg), *val); - } - return 0; - -badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - ucontext_t *uc = arg; - unw_fpreg_t *addr; - - /* Allow only 32 fregs and 32 vregs */ - if (!(((unsigned) (reg - UNW_PPC64_F0) < 32) - ||((unsigned) (reg - UNW_PPC64_V0) < 32))) - goto badreg; - - addr = uc_addr (uc, reg); - if (!addr) - goto badreg; - - if (write) - { - Debug (12, "%s <- %016Lf\n", unw_regname (reg), *val); - *(unw_fpreg_t *) addr = *val; - } - else - { - *val = *(unw_fpreg_t *) addr; - Debug (12, "%s -> %016Lf\n", unw_regname (reg), *val); - } - return 0; - -badreg: - Debug (1, "bad register number %u\n", reg); - /* attempt to access a non-preserved register */ - return -UNW_EBADREG; -} - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp); -} - -HIDDEN void -ppc64_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); -#if _CALL_ELF == 2 - local_addr_space.abi = UNW_PPC64_ABI_ELFv2; -#else - local_addr_space.abi = UNW_PPC64_ABI_ELFv1; -#endif - local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; - local_addr_space.acc.find_proc_info = dwarf_find_proc_info; - local_addr_space.acc.put_unwind_info = put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = ppc64_local_resume; - local_addr_space.acc.get_proc_name = get_static_proc_name; - unw_flush_cache (&local_addr_space, 0, 0); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/ppc64/Greg_states_iterate.c b/contrib/libunwind/src/ppc64/Greg_states_iterate.c deleted file mode 100644 index a39837a1781..00000000000 --- a/contrib/libunwind/src/ppc64/Greg_states_iterate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_reg_states_iterate (&c->dwarf, cb, token); -} diff --git a/contrib/libunwind/src/ppc64/Gregs.c b/contrib/libunwind/src/ppc64/Gregs.c deleted file mode 100644 index 1cb5d9dc653..00000000000 --- a/contrib/libunwind/src/ppc64/Gregs.c +++ /dev/null @@ -1,141 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - struct dwarf_loc loc; - - switch (reg) - { - case UNW_PPC64_R0: - case UNW_PPC64_R2: - case UNW_PPC64_R3: - case UNW_PPC64_R4: - case UNW_PPC64_R5: - case UNW_PPC64_R6: - case UNW_PPC64_R7: - case UNW_PPC64_R8: - case UNW_PPC64_R9: - case UNW_PPC64_R10: - case UNW_PPC64_R11: - case UNW_PPC64_R12: - case UNW_PPC64_R13: - case UNW_PPC64_R14: - case UNW_PPC64_R15: - case UNW_PPC64_R16: - case UNW_PPC64_R17: - case UNW_PPC64_R18: - case UNW_PPC64_R19: - case UNW_PPC64_R20: - case UNW_PPC64_R21: - case UNW_PPC64_R22: - case UNW_PPC64_R23: - case UNW_PPC64_R24: - case UNW_PPC64_R25: - case UNW_PPC64_R26: - case UNW_PPC64_R27: - case UNW_PPC64_R28: - case UNW_PPC64_R29: - case UNW_PPC64_R30: - case UNW_PPC64_R31: - case UNW_PPC64_LR: - case UNW_PPC64_CTR: - case UNW_PPC64_CR0: - case UNW_PPC64_CR1: - case UNW_PPC64_CR2: - case UNW_PPC64_CR3: - case UNW_PPC64_CR4: - case UNW_PPC64_CR5: - case UNW_PPC64_CR6: - case UNW_PPC64_CR7: - case UNW_PPC64_VRSAVE: - case UNW_PPC64_VSCR: - case UNW_PPC64_SPE_ACC: - case UNW_PPC64_SPEFSCR: - loc = c->dwarf.loc[reg]; - break; - - case UNW_TDEP_IP: - if (write) - { - c->dwarf.ip = *valp; /* update the IP cache */ - if (c->dwarf.pi_valid && (*valp < c->dwarf.pi.start_ip - || *valp >= c->dwarf.pi.end_ip)) - c->dwarf.pi_valid = 0; /* new IP outside of current proc */ - } - else - *valp = c->dwarf.ip; - return 0; - - case UNW_TDEP_SP: - if (write) - return -UNW_EREADONLYREG; - *valp = c->dwarf.cfa; - return 0; - - default: - return -UNW_EBADREG; - break; - } - - if (write) - return dwarf_put (&c->dwarf, loc, *valp); - else - return dwarf_get (&c->dwarf, loc, valp); -} - -HIDDEN int -tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, - int write) -{ - struct dwarf_loc loc; - - if ((unsigned) (reg - UNW_PPC64_F0) < 32) - { - loc = c->dwarf.loc[reg]; - if (write) - return dwarf_putfp (&c->dwarf, loc, *valp); - else - return dwarf_getfp (&c->dwarf, loc, valp); - } - else - if ((unsigned) (reg - UNW_PPC64_V0) < 32) - { - loc = c->dwarf.loc[reg]; - if (write) - return dwarf_putvr (&c->dwarf, loc, *valp); - else - return dwarf_getvr (&c->dwarf, loc, valp); - } - - return -UNW_EBADREG; -} - diff --git a/contrib/libunwind/src/ppc64/Gresume.c b/contrib/libunwind/src/ppc64/Gresume.c deleted file mode 100644 index 3f850e937df..00000000000 --- a/contrib/libunwind/src/ppc64/Gresume.c +++ /dev/null @@ -1,111 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford cjashfor@us.ibm.com - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -#ifndef UNW_REMOTE_ONLY - -#include - -/* sigreturn() is a no-op on x86_64 glibc. */ - -static NORETURN inline long -my_rt_sigreturn (void *new_sp) -{ - /* XXX: empty stub. */ - abort (); -} - -HIDDEN inline int -ppc64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ - struct cursor *c = (struct cursor *) cursor; - ucontext_t *uc = (ucontext_t *)c->dwarf.as_arg; - - if (unlikely (c->sigcontext_format != PPC_SCF_NONE)) - { - my_rt_sigreturn(cursor); - abort(); - } - else - { - Debug (8, "resuming at ip=%llx via setcontext()\n", - (unsigned long long) c->dwarf.ip); - setcontext (uc); - } - return -UNW_EINVAL; -} - -#endif /* !UNW_REMOTE_ONLY */ - -/* This routine is responsible for copying the register values in - cursor C and establishing them as the current machine state. */ - -static inline int -establish_machine_state (struct cursor *c) -{ - unw_addr_space_t as = c->dwarf.as; - void *arg = c->dwarf.as_arg; - unw_fpreg_t fpval; - unw_word_t val; - int reg; - - Debug (8, "copying out cursor state\n"); - - for (reg = 0; reg <= UNW_REG_LAST; ++reg) - { - Debug (16, "copying %s %d\n", unw_regname (reg), reg); - if (unw_is_fpreg (reg)) - { - if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) - as->acc.access_fpreg (as, reg, &fpval, 1, arg); - } - else - { - if (tdep_access_reg (c, reg, &val, 0) >= 0) - as->acc.access_reg (as, reg, &val, 1, arg); - } - } - return 0; -} - -PROTECTED int -unw_resume (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - Debug (1, "(cursor=%p)\n", c); - - if ((ret = establish_machine_state (c)) < 0) - return ret; - - return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, - c->dwarf.as_arg); -} diff --git a/contrib/libunwind/src/ppc64/Gstep.c b/contrib/libunwind/src/ppc64/Gstep.c deleted file mode 100644 index 58a5ad87fe4..00000000000 --- a/contrib/libunwind/src/ppc64/Gstep.c +++ /dev/null @@ -1,466 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "ucontext_i.h" -#include "remote.h" -#include - -/* This definition originates in /usr/include/asm-ppc64/ptrace.h, but is - defined there only when __KERNEL__ is defined. We reproduce it here for - our use at the user level in order to locate the ucontext record, which - appears to be at this offset relative to the stack pointer when in the - context of the signal handler return trampoline code - - __kernel_sigtramp_rt64. */ -#define __SIGNAL_FRAMESIZE 128 - -/* This definition comes from the document "64-bit PowerPC ELF Application - Binary Interface Supplement 1.9", section 3.2.2. - http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK */ - -typedef struct -{ - long unsigned back_chain; - long unsigned cr_save; - long unsigned lr_save; - /* many more fields here, but they are unused by this code */ -} stack_frame_t; - - -PROTECTED int -unw_step (unw_cursor_t * cursor) -{ - struct cursor *c = (struct cursor *) cursor; - stack_frame_t dummy; - unw_word_t back_chain_offset, lr_save_offset, v_regs_ptr; - struct dwarf_loc back_chain_loc, lr_save_loc, sp_loc, ip_loc, v_regs_loc; - int ret, i; - - Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->dwarf.ip); - - /* Try DWARF-based unwinding... */ - - ret = dwarf_step (&c->dwarf); - - if (ret < 0 && ret != -UNW_ENOINFO) - { - Debug (2, "returning %d\n", ret); - return ret; - } - - if (unlikely (ret < 0)) - { - if (likely (unw_is_signal_frame (cursor) <= 0)) - { - /* DWARF unwinding failed. As of 09/26/2006, gcc in 64-bit mode - produces the mandatory level of traceback record in the code, but - I get the impression that this is transitory, that eventually gcc - will not produce any traceback records at all. So, for now, we - won't bother to try to find and use these records. - - We can, however, attempt to unwind the frame by using the callback - chain. This is very crude, however, and won't be able to unwind - any registers besides the IP, SP, and LR . */ - - back_chain_offset = ((void *) &dummy.back_chain - (void *) &dummy); - lr_save_offset = ((void *) &dummy.lr_save - (void *) &dummy); - - back_chain_loc = DWARF_LOC (c->dwarf.cfa + back_chain_offset, 0); - - if ((ret = - dwarf_get (&c->dwarf, back_chain_loc, &c->dwarf.cfa)) < 0) - { - Debug (2, - "Unable to retrieve CFA from back chain in stack frame - %d\n", - ret); - return ret; - } - if (c->dwarf.cfa == 0) - /* Unless the cursor or stack is corrupt or uninitialized we've most - likely hit the top of the stack */ - return 0; - - lr_save_loc = DWARF_LOC (c->dwarf.cfa + lr_save_offset, 0); - - if ((ret = dwarf_get (&c->dwarf, lr_save_loc, &c->dwarf.ip)) < 0) - { - Debug (2, - "Unable to retrieve IP from lr save in stack frame - %d\n", - ret); - return ret; - } - - /* Mark all registers unsaved */ - for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - - ret = 1; - } - else - { - /* Find the sigcontext record by taking the CFA and adjusting by - the dummy signal frame size. - - Note that there isn't any way to determined if SA_SIGINFO was - set in the sa_flags parameter to sigaction when the signal - handler was established. If it was not set, the ucontext - record is not required to be on the stack, in which case the - following code will likely cause a seg fault or other crash - condition. */ - - unw_word_t ucontext = c->dwarf.cfa + __SIGNAL_FRAMESIZE; - - Debug (1, "signal frame, skip over trampoline\n"); - - c->sigcontext_format = PPC_SCF_LINUX_RT_SIGFRAME; - c->sigcontext_addr = ucontext; - - sp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0); - ip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_NIP, 0); - - ret = dwarf_get (&c->dwarf, sp_loc, &c->dwarf.cfa); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - ret = dwarf_get (&c->dwarf, ip_loc, &c->dwarf.ip); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - - /* Instead of just restoring the non-volatile registers, do all - of the registers for now. This will incur a performance hit, - but it's rare enough not to cause too much of a problem, and - might be useful in some cases. */ - c->dwarf.loc[UNW_PPC64_R0] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R0, 0); - c->dwarf.loc[UNW_PPC64_R1] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0); - c->dwarf.loc[UNW_PPC64_R2] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R2, 0); - c->dwarf.loc[UNW_PPC64_R3] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R3, 0); - c->dwarf.loc[UNW_PPC64_R4] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R4, 0); - c->dwarf.loc[UNW_PPC64_R5] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R5, 0); - c->dwarf.loc[UNW_PPC64_R6] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R6, 0); - c->dwarf.loc[UNW_PPC64_R7] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R7, 0); - c->dwarf.loc[UNW_PPC64_R8] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); - c->dwarf.loc[UNW_PPC64_R9] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); - c->dwarf.loc[UNW_PPC64_R10] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); - c->dwarf.loc[UNW_PPC64_R11] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); - c->dwarf.loc[UNW_PPC64_R12] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); - c->dwarf.loc[UNW_PPC64_R13] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); - c->dwarf.loc[UNW_PPC64_R14] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); - c->dwarf.loc[UNW_PPC64_R15] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); - c->dwarf.loc[UNW_PPC64_R16] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R16, 0); - c->dwarf.loc[UNW_PPC64_R17] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R17, 0); - c->dwarf.loc[UNW_PPC64_R18] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R18, 0); - c->dwarf.loc[UNW_PPC64_R19] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R19, 0); - c->dwarf.loc[UNW_PPC64_R20] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R20, 0); - c->dwarf.loc[UNW_PPC64_R21] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R21, 0); - c->dwarf.loc[UNW_PPC64_R22] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R22, 0); - c->dwarf.loc[UNW_PPC64_R23] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R23, 0); - c->dwarf.loc[UNW_PPC64_R24] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R24, 0); - c->dwarf.loc[UNW_PPC64_R25] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R25, 0); - c->dwarf.loc[UNW_PPC64_R26] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R26, 0); - c->dwarf.loc[UNW_PPC64_R27] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R27, 0); - c->dwarf.loc[UNW_PPC64_R28] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R28, 0); - c->dwarf.loc[UNW_PPC64_R29] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R29, 0); - c->dwarf.loc[UNW_PPC64_R30] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R30, 0); - c->dwarf.loc[UNW_PPC64_R31] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R31, 0); - - c->dwarf.loc[UNW_PPC64_LR] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0); - c->dwarf.loc[UNW_PPC64_CTR] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CTR, 0); - /* This CR0 assignment is probably wrong. There are 8 dwarf columns - assigned to the CR registers, but only one CR register in the - mcontext structure */ - c->dwarf.loc[UNW_PPC64_CR0] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CCR, 0); - c->dwarf.loc[UNW_PPC64_XER] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_XER, 0); - c->dwarf.loc[UNW_PPC64_NIP] = - DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_NIP, 0); - - /* TODO: Is there a way of obtaining the value of the - pseudo frame pointer (which is sp + some fixed offset, I - assume), based on the contents of the ucontext record - structure? For now, set this loc to null. */ - c->dwarf.loc[UNW_PPC64_FRAME_POINTER] = DWARF_NULL_LOC; - - c->dwarf.loc[UNW_PPC64_F0] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R0, 0); - c->dwarf.loc[UNW_PPC64_F1] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R1, 0); - c->dwarf.loc[UNW_PPC64_F2] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R2, 0); - c->dwarf.loc[UNW_PPC64_F3] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R3, 0); - c->dwarf.loc[UNW_PPC64_F4] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R4, 0); - c->dwarf.loc[UNW_PPC64_F5] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R5, 0); - c->dwarf.loc[UNW_PPC64_F6] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R6, 0); - c->dwarf.loc[UNW_PPC64_F7] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R7, 0); - c->dwarf.loc[UNW_PPC64_F8] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R8, 0); - c->dwarf.loc[UNW_PPC64_F9] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R9, 0); - c->dwarf.loc[UNW_PPC64_F10] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R10, 0); - c->dwarf.loc[UNW_PPC64_F11] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R11, 0); - c->dwarf.loc[UNW_PPC64_F12] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R12, 0); - c->dwarf.loc[UNW_PPC64_F13] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R13, 0); - c->dwarf.loc[UNW_PPC64_F14] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R14, 0); - c->dwarf.loc[UNW_PPC64_F15] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R15, 0); - c->dwarf.loc[UNW_PPC64_F16] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R16, 0); - c->dwarf.loc[UNW_PPC64_F17] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R17, 0); - c->dwarf.loc[UNW_PPC64_F18] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R18, 0); - c->dwarf.loc[UNW_PPC64_F19] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R19, 0); - c->dwarf.loc[UNW_PPC64_F20] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R20, 0); - c->dwarf.loc[UNW_PPC64_F21] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R21, 0); - c->dwarf.loc[UNW_PPC64_F22] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R22, 0); - c->dwarf.loc[UNW_PPC64_F23] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R23, 0); - c->dwarf.loc[UNW_PPC64_F24] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R24, 0); - c->dwarf.loc[UNW_PPC64_F25] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R25, 0); - c->dwarf.loc[UNW_PPC64_F26] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R26, 0); - c->dwarf.loc[UNW_PPC64_F27] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R27, 0); - c->dwarf.loc[UNW_PPC64_F28] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R28, 0); - c->dwarf.loc[UNW_PPC64_F29] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R29, 0); - c->dwarf.loc[UNW_PPC64_F30] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R30, 0); - c->dwarf.loc[UNW_PPC64_F31] = - DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R31, 0); - /* Note that there is no .eh_section register column for the - FPSCR register. I don't know why this is. */ - - v_regs_loc = DWARF_LOC (ucontext + UC_MCONTEXT_V_REGS, 0); - ret = dwarf_get (&c->dwarf, v_regs_loc, &v_regs_ptr); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - if (v_regs_ptr != 0) - { - /* The v_regs_ptr is not null. Set all of the AltiVec locs */ - - c->dwarf.loc[UNW_PPC64_V0] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R0, 0); - c->dwarf.loc[UNW_PPC64_V1] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R1, 0); - c->dwarf.loc[UNW_PPC64_V2] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R2, 0); - c->dwarf.loc[UNW_PPC64_V3] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R3, 0); - c->dwarf.loc[UNW_PPC64_V4] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R4, 0); - c->dwarf.loc[UNW_PPC64_V5] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R5, 0); - c->dwarf.loc[UNW_PPC64_V6] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R6, 0); - c->dwarf.loc[UNW_PPC64_V7] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R7, 0); - c->dwarf.loc[UNW_PPC64_V8] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R8, 0); - c->dwarf.loc[UNW_PPC64_V9] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R9, 0); - c->dwarf.loc[UNW_PPC64_V10] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R10, 0); - c->dwarf.loc[UNW_PPC64_V11] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R11, 0); - c->dwarf.loc[UNW_PPC64_V12] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R12, 0); - c->dwarf.loc[UNW_PPC64_V13] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R13, 0); - c->dwarf.loc[UNW_PPC64_V14] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R14, 0); - c->dwarf.loc[UNW_PPC64_V15] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R15, 0); - c->dwarf.loc[UNW_PPC64_V16] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R16, 0); - c->dwarf.loc[UNW_PPC64_V17] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R17, 0); - c->dwarf.loc[UNW_PPC64_V18] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R18, 0); - c->dwarf.loc[UNW_PPC64_V19] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R19, 0); - c->dwarf.loc[UNW_PPC64_V20] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R20, 0); - c->dwarf.loc[UNW_PPC64_V21] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R21, 0); - c->dwarf.loc[UNW_PPC64_V22] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R22, 0); - c->dwarf.loc[UNW_PPC64_V23] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R23, 0); - c->dwarf.loc[UNW_PPC64_V24] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R24, 0); - c->dwarf.loc[UNW_PPC64_V25] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R25, 0); - c->dwarf.loc[UNW_PPC64_V26] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R26, 0); - c->dwarf.loc[UNW_PPC64_V27] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R27, 0); - c->dwarf.loc[UNW_PPC64_V28] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R28, 0); - c->dwarf.loc[UNW_PPC64_V29] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R29, 0); - c->dwarf.loc[UNW_PPC64_V30] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R30, 0); - c->dwarf.loc[UNW_PPC64_V31] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R31, 0); - c->dwarf.loc[UNW_PPC64_VRSAVE] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VRSAVE, 0); - c->dwarf.loc[UNW_PPC64_VSCR] = - DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VSCR, 0); - } - else - { - c->dwarf.loc[UNW_PPC64_V0] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V1] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V2] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V3] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V4] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V5] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V6] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V7] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V8] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V9] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V10] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V11] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V12] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V13] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V14] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V15] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V16] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V17] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V18] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V19] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V20] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V21] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V22] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V23] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V24] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V25] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V26] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V27] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V28] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V29] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V30] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_V31] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_VRSAVE] = DWARF_NULL_LOC; - c->dwarf.loc[UNW_PPC64_VSCR] = DWARF_NULL_LOC; - } - ret = 1; - } - } - - if (c->dwarf.ip == 0) - { - /* Unless the cursor or stack is corrupt or uninitialized, - we've most likely hit the top of the stack */ - Debug (2, "returning 0\n"); - return 0; - } - - // on ppc64, R2 register is used as pointer to TOC - // section which is used for symbol lookup in PIC code - // ppc64 linker generates "ld r2, 40(r1)" (ELFv1) or - // "ld r2, 24(r1)" (ELFv2) instruction after each - // @plt call. We need restore R2, but only for @plt calls - { - unw_word_t ip = c->dwarf.ip; - unw_addr_space_t as = c->dwarf.as; - unw_accessors_t *a = unw_get_accessors (as); - void *arg = c->dwarf.as_arg; - uint32_t toc_save = (as->abi == UNW_PPC64_ABI_ELFv2)? 24 : 40; - int32_t inst; - - if (fetch32 (as, a, &ip, &inst, arg) >= 0 - && (uint32_t)inst == (0xE8410000U + toc_save)) - { - // @plt call, restoring R2 from CFA+toc_save - c->dwarf.loc[UNW_PPC64_R2] = DWARF_LOC(c->dwarf.cfa + toc_save, 0); - } - } - - Debug (2, "returning %d with last return statement\n", ret); - return ret; -} diff --git a/contrib/libunwind/src/ppc64/Lapply_reg_state.c b/contrib/libunwind/src/ppc64/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/ppc64/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/ppc64/Lcreate_addr_space.c b/contrib/libunwind/src/ppc64/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901..00000000000 --- a/contrib/libunwind/src/ppc64/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/contrib/libunwind/src/ppc64/Lglobal.c b/contrib/libunwind/src/ppc64/Lglobal.c deleted file mode 100644 index 6d7b489e14b..00000000000 --- a/contrib/libunwind/src/ppc64/Lglobal.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/contrib/libunwind/src/ppc64/Linit.c b/contrib/libunwind/src/ppc64/Linit.c deleted file mode 100644 index e9abfdd46a3..00000000000 --- a/contrib/libunwind/src/ppc64/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/contrib/libunwind/src/ppc64/Lreg_states_iterate.c b/contrib/libunwind/src/ppc64/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/ppc64/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/ppc64/Lregs.c b/contrib/libunwind/src/ppc64/Lregs.c deleted file mode 100644 index 2c9c75cd7d9..00000000000 --- a/contrib/libunwind/src/ppc64/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/contrib/libunwind/src/ppc64/Lresume.c b/contrib/libunwind/src/ppc64/Lresume.c deleted file mode 100644 index 41a8cf003de..00000000000 --- a/contrib/libunwind/src/ppc64/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/contrib/libunwind/src/ppc64/Lstep.c b/contrib/libunwind/src/ppc64/Lstep.c deleted file mode 100644 index c1ac3c7547f..00000000000 --- a/contrib/libunwind/src/ppc64/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/contrib/libunwind/src/ppc64/get_func_addr.c b/contrib/libunwind/src/ppc64/get_func_addr.c deleted file mode 100644 index 13abb7db885..00000000000 --- a/contrib/libunwind/src/ppc64/get_func_addr.c +++ /dev/null @@ -1,51 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -int -tdep_get_func_addr (unw_addr_space_t as, unw_word_t addr, - unw_word_t *entry_point) -{ - if (as->abi == UNW_PPC64_ABI_ELFv1) - { - unw_accessors_t *a; - int ret; - - a = unw_get_accessors (as); - /* Entry-point is stored in the 1st word of the function descriptor. - In case that changes in the future, we'd have to update the line - below and read the word at addr + offset: */ - ret = (*a->access_mem) (as, addr, entry_point, 0, NULL); - if (ret < 0) - return ret; - } - else - *entry_point = addr; - - return 0; -} diff --git a/contrib/libunwind/src/ppc64/init.h b/contrib/libunwind/src/ppc64/init.h deleted file mode 100644 index 9b8139343d6..00000000000 --- a/contrib/libunwind/src/ppc64/init.h +++ /dev/null @@ -1,82 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static inline int -common_init_ppc64 (struct cursor *c, unsigned use_prev_instr) -{ - int ret; - int i; - - for (i = UNW_PPC64_R0; i <= UNW_PPC64_R31; i++) { - c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, i); - } - for (i = UNW_PPC64_F0; i <= UNW_PPC64_F31; i++) { - c->dwarf.loc[i] = DWARF_FPREG_LOC (&c->dwarf, i); - } - for (i = UNW_PPC64_V0; i <= UNW_PPC64_V31; i++) { - c->dwarf.loc[i] = DWARF_VREG_LOC (&c->dwarf, i); - } - - for (i = UNW_PPC64_CR0; i <= UNW_PPC64_CR7; i++) { - c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, i); - } - c->dwarf.loc[UNW_PPC64_ARG_POINTER] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_ARG_POINTER); - c->dwarf.loc[UNW_PPC64_CTR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_CTR); - c->dwarf.loc[UNW_PPC64_VSCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_VSCR); - - c->dwarf.loc[UNW_PPC64_XER] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_XER); - c->dwarf.loc[UNW_PPC64_LR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_LR); - c->dwarf.loc[UNW_PPC64_VRSAVE] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_VRSAVE); - c->dwarf.loc[UNW_PPC64_SPEFSCR] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_SPEFSCR); - c->dwarf.loc[UNW_PPC64_SPE_ACC] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_SPE_ACC); - - c->dwarf.loc[UNW_PPC64_NIP] = DWARF_REG_LOC (&c->dwarf, UNW_PPC64_NIP); - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_PPC64_NIP], &c->dwarf.ip); - if (ret < 0) - return ret; - - ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_PPC64_R1), - &c->dwarf.cfa); - if (ret < 0) - return ret; - - c->sigcontext_format = PPC_SCF_NONE; - c->sigcontext_addr = 0; - - c->dwarf.args_size = 0; - c->dwarf.stash_frames = 0; - c->dwarf.use_prev_instr = use_prev_instr; - c->dwarf.pi_valid = 0; - c->dwarf.pi_is_dynamic = 0; - c->dwarf.hint = 0; - c->dwarf.prev_rs = 0; - - return 0; -} diff --git a/contrib/libunwind/src/ppc64/is_fpreg.c b/contrib/libunwind/src/ppc64/is_fpreg.c deleted file mode 100644 index b34bf8715c7..00000000000 --- a/contrib/libunwind/src/ppc64/is_fpreg.c +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_is_fpreg (int regnum) -{ - return (regnum >= UNW_PPC64_F0 && regnum <= UNW_PPC64_F31); -} diff --git a/contrib/libunwind/src/ppc64/regname.c b/contrib/libunwind/src/ppc64/regname.c deleted file mode 100644 index 3e3a1419888..00000000000 --- a/contrib/libunwind/src/ppc64/regname.c +++ /dev/null @@ -1,164 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static const char *regname[] = - { - [UNW_PPC64_R0]="GPR0", - [UNW_PPC64_R1]="GPR1", - [UNW_PPC64_R2]="GPR2", - [UNW_PPC64_R3]="GPR3", - [UNW_PPC64_R4]="GPR4", - [UNW_PPC64_R5]="GPR5", - [UNW_PPC64_R6]="GPR6", - [UNW_PPC64_R7]="GPR7", - [UNW_PPC64_R8]="GPR8", - [UNW_PPC64_R9]="GPR9", - [UNW_PPC64_R10]="GPR10", - [UNW_PPC64_R11]="GPR11", - [UNW_PPC64_R12]="GPR12", - [UNW_PPC64_R13]="GPR13", - [UNW_PPC64_R14]="GPR14", - [UNW_PPC64_R15]="GPR15", - [UNW_PPC64_R16]="GPR16", - [UNW_PPC64_R17]="GPR17", - [UNW_PPC64_R18]="GPR18", - [UNW_PPC64_R19]="GPR19", - [UNW_PPC64_R20]="GPR20", - [UNW_PPC64_R21]="GPR21", - [UNW_PPC64_R22]="GPR22", - [UNW_PPC64_R23]="GPR23", - [UNW_PPC64_R24]="GPR24", - [UNW_PPC64_R25]="GPR25", - [UNW_PPC64_R26]="GPR26", - [UNW_PPC64_R27]="GPR27", - [UNW_PPC64_R28]="GPR28", - [UNW_PPC64_R29]="GPR29", - [UNW_PPC64_R30]="GPR30", - [UNW_PPC64_R31]="GPR31", - - [UNW_PPC64_F0]="FPR0", - [UNW_PPC64_F1]="FPR1", - [UNW_PPC64_F2]="FPR2", - [UNW_PPC64_F3]="FPR3", - [UNW_PPC64_F4]="FPR4", - [UNW_PPC64_F5]="FPR5", - [UNW_PPC64_F6]="FPR6", - [UNW_PPC64_F7]="FPR7", - [UNW_PPC64_F8]="FPR8", - [UNW_PPC64_F9]="FPR9", - [UNW_PPC64_F10]="FPR10", - [UNW_PPC64_F11]="FPR11", - [UNW_PPC64_F12]="FPR12", - [UNW_PPC64_F13]="FPR13", - [UNW_PPC64_F14]="FPR14", - [UNW_PPC64_F15]="FPR15", - [UNW_PPC64_F16]="FPR16", - [UNW_PPC64_F17]="FPR17", - [UNW_PPC64_F18]="FPR18", - [UNW_PPC64_F19]="FPR19", - [UNW_PPC64_F20]="FPR20", - [UNW_PPC64_F21]="FPR21", - [UNW_PPC64_F22]="FPR22", - [UNW_PPC64_F23]="FPR23", - [UNW_PPC64_F24]="FPR24", - [UNW_PPC64_F25]="FPR25", - [UNW_PPC64_F26]="FPR26", - [UNW_PPC64_F27]="FPR27", - [UNW_PPC64_F28]="FPR28", - [UNW_PPC64_F29]="FPR29", - [UNW_PPC64_F30]="FPR30", - [UNW_PPC64_F31]="FPR31", - - [UNW_PPC64_LR]="LR", - [UNW_PPC64_CTR]="CTR", - [UNW_PPC64_ARG_POINTER]="ARG_POINTER", - - [UNW_PPC64_CR0]="CR0", - [UNW_PPC64_CR1]="CR1", - [UNW_PPC64_CR2]="CR2", - [UNW_PPC64_CR3]="CR3", - [UNW_PPC64_CR4]="CR4", - [UNW_PPC64_CR5]="CR5", - [UNW_PPC64_CR6]="CR6", - [UNW_PPC64_CR7]="CR7", - - [UNW_PPC64_XER]="XER", - - [UNW_PPC64_V0]="VR0", - [UNW_PPC64_V1]="VR1", - [UNW_PPC64_V2]="VR2", - [UNW_PPC64_V3]="VR3", - [UNW_PPC64_V4]="VR4", - [UNW_PPC64_V5]="VR5", - [UNW_PPC64_V6]="VR6", - [UNW_PPC64_V7]="VR7", - [UNW_PPC64_V8]="VR8", - [UNW_PPC64_V9]="VR9", - [UNW_PPC64_V10]="VR10", - [UNW_PPC64_V11]="VR11", - [UNW_PPC64_V12]="VR12", - [UNW_PPC64_V13]="VR13", - [UNW_PPC64_V14]="VR14", - [UNW_PPC64_V15]="VR15", - [UNW_PPC64_V16]="VR16", - [UNW_PPC64_V17]="VR17", - [UNW_PPC64_V18]="VR18", - [UNW_PPC64_V19]="VR19", - [UNW_PPC64_V20]="VR20", - [UNW_PPC64_V21]="VR21", - [UNW_PPC64_V22]="VR22", - [UNW_PPC64_V23]="VR23", - [UNW_PPC64_V24]="VR24", - [UNW_PPC64_V25]="VR25", - [UNW_PPC64_V26]="VR26", - [UNW_PPC64_V27]="VR27", - [UNW_PPC64_V28]="VR28", - [UNW_PPC64_V29]="VR29", - [UNW_PPC64_V30]="VR30", - [UNW_PPC64_V31]="VR31", - - [UNW_PPC64_VSCR]="VSCR", - - [UNW_PPC64_VRSAVE]="VRSAVE", - [UNW_PPC64_SPE_ACC]="SPE_ACC", - [UNW_PPC64_SPEFSCR]="SPEFSCR", - - [UNW_PPC64_FRAME_POINTER]="FRAME_POINTER", - [UNW_PPC64_NIP]="NIP", - - }; - -PROTECTED const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) - return regname[reg]; - else - return "???"; -} diff --git a/contrib/libunwind/src/ppc64/setcontext.S b/contrib/libunwind/src/ppc64/setcontext.S deleted file mode 100644 index ffc2500a517..00000000000 --- a/contrib/libunwind/src/ppc64/setcontext.S +++ /dev/null @@ -1,9 +0,0 @@ - .global _UI_setcontext - -_UI_setcontext: - blr - -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif diff --git a/contrib/libunwind/src/ppc64/ucontext_i.h b/contrib/libunwind/src/ppc64/ucontext_i.h deleted file mode 100644 index 2ddfdb865a7..00000000000 --- a/contrib/libunwind/src/ppc64/ucontext_i.h +++ /dev/null @@ -1,173 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef ucontext_i_h -#define ucontext_i_h - -#include - -/* These values were derived by reading - /usr/src/linux-2.6.18-1.8/arch/um/include/sysdep-ppc/ptrace.h and - /usr/src/linux-2.6.18-1.8/arch/powerpc/kernel/ppc32.h -*/ - -#define NIP_IDX 32 -#define MSR_IDX 33 -#define ORIG_GPR3_IDX 34 -#define CTR_IDX 35 -#define LINK_IDX 36 -#define XER_IDX 37 -#define CCR_IDX 38 -#define SOFTE_IDX 39 -#define TRAP_IDX 40 -#define DAR_IDX 41 -#define DSISR_IDX 42 -#define RESULT_IDX 43 - -#define VSCR_IDX 32 -#define VRSAVE_IDX 33 - -/* These are dummy structures used only for obtaining the offsets of the - various structure members. */ -static ucontext_t dmy_ctxt; -static vrregset_t dmy_vrregset; - -#define UC_MCONTEXT_GREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[0] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[1] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[2] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[3] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[4] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[5] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[6] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[7] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[8] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[9] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[10] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[11] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[12] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[13] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[14] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[15] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[16] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[17] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[18] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[19] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[20] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[21] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[22] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[23] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[24] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[25] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[26] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[27] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[28] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[29] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[30] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[31] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_NIP ((void *)&dmy_ctxt.uc_mcontext.gp_regs[NIP_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_MSR ((void *)&dmy_ctxt.uc_mcontext.gp_regs[MSR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_ORIG_GPR3 ((void *)&dmy_ctxt.uc_mcontext.gp_regs[ORIG_GPR3_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_CTR ((void *)&dmy_ctxt.uc_mcontext.gp_regs[CTR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_LINK ((void *)&dmy_ctxt.uc_mcontext.gp_regs[LINK_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_XER ((void *)&dmy_ctxt.uc_mcontext.gp_regs[XER_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_CCR ((void *)&dmy_ctxt.uc_mcontext.gp_regs[CCR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_SOFTE ((void *)&dmy_ctxt.uc_mcontext.gp_regs[SOFTE_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_TRAP ((void *)&dmy_ctxt.uc_mcontext.gp_regs[TRAP_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_DAR ((void *)&dmy_ctxt.uc_mcontext.gp_regs[DAR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_DSISR ((void *)&dmy_ctxt.uc_mcontext.gp_regs[DSISR_IDX] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_GREGS_RESULT ((void *)&dmy_ctxt.uc_mcontext.gp_regs[RESULT_IDX] - (void *)&dmy_ctxt) - -#define UC_MCONTEXT_FREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[0] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[1] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[2] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[3] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[4] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[5] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[6] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[7] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[8] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[9] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[10] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[11] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[12] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[13] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[14] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[15] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[16] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[17] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[18] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[19] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[20] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[21] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[22] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[23] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[24] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[25] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[26] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[27] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[28] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[29] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[30] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.fp_regs[31] - (void *)&dmy_ctxt) -#define UC_MCONTEXT_FREGS_FPSCR ((void *)&dmy_ctxt.uc_mcontext.fp_regs[32] - (void *)&dmy_ctxt) - -#define UC_MCONTEXT_V_REGS ((void *)&dmy_ctxt.uc_mcontext.v_regs - (void *)&dmy_ctxt) - -#define UC_MCONTEXT_VREGS_R0 ((void *)&dmy_vrregset.vrregs[0] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R1 ((void *)&dmy_vrregset.vrregs[1] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R2 ((void *)&dmy_vrregset.vrregs[2] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R3 ((void *)&dmy_vrregset.vrregs[3] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R4 ((void *)&dmy_vrregset.vrregs[4] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R5 ((void *)&dmy_vrregset.vrregs[5] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R6 ((void *)&dmy_vrregset.vrregs[6] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R7 ((void *)&dmy_vrregset.vrregs[7] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R8 ((void *)&dmy_vrregset.vrregs[8] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R9 ((void *)&dmy_vrregset.vrregs[9] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R10 ((void *)&dmy_vrregset.vrregs[10] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R11 ((void *)&dmy_vrregset.vrregs[11] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R12 ((void *)&dmy_vrregset.vrregs[12] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R13 ((void *)&dmy_vrregset.vrregs[13] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R14 ((void *)&dmy_vrregset.vrregs[14] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R15 ((void *)&dmy_vrregset.vrregs[15] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R16 ((void *)&dmy_vrregset.vrregs[16] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R17 ((void *)&dmy_vrregset.vrregs[17] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R18 ((void *)&dmy_vrregset.vrregs[18] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R19 ((void *)&dmy_vrregset.vrregs[19] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R20 ((void *)&dmy_vrregset.vrregs[20] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R21 ((void *)&dmy_vrregset.vrregs[21] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R22 ((void *)&dmy_vrregset.vrregs[22] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R23 ((void *)&dmy_vrregset.vrregs[23] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R24 ((void *)&dmy_vrregset.vrregs[24] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R25 ((void *)&dmy_vrregset.vrregs[25] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R26 ((void *)&dmy_vrregset.vrregs[26] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R27 ((void *)&dmy_vrregset.vrregs[27] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R28 ((void *)&dmy_vrregset.vrregs[28] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R29 ((void *)&dmy_vrregset.vrregs[29] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R30 ((void *)&dmy_vrregset.vrregs[30] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_R31 ((void *)&dmy_vrregset.vrregs[31] - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_VSCR ((void *)&dmy_vrregset.vscr - (void *)&dmy_vrregset) -#define UC_MCONTEXT_VREGS_VRSAVE ((void *)&dmy_vrregset.vrsave - (void *)&dmy_vrregset) - -#endif diff --git a/contrib/libunwind/src/ppc64/unwind_i.h b/contrib/libunwind/src/ppc64/unwind_i.h deleted file mode 100644 index 26bbc2df83a..00000000000 --- a/contrib/libunwind/src/ppc64/unwind_i.h +++ /dev/null @@ -1,52 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2006-2007 IBM - Contributed by - Corey Ashford - Jose Flavio Aguilar Paulino - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include - -#include - -#include -#include - -#define ppc64_lock UNW_OBJ(lock) -#define ppc64_local_resume UNW_OBJ(local_resume) -#define ppc64_local_addr_space_init UNW_OBJ(local_addr_space_init) -#if 0 -#define ppc64_scratch_loc UNW_OBJ(scratch_loc) -#endif - -extern void ppc64_local_addr_space_init (void); -extern int ppc64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, - void *arg); -#if 0 -extern dwarf_loc_t ppc64_scratch_loc (struct cursor *c, unw_regnum_t reg); -#endif - -#endif /* unwind_i_h */ diff --git a/contrib/libunwind/src/ptrace/_UPT_access_fpreg.c b/contrib/libunwind/src/ptrace/_UPT_access_fpreg.c deleted file mode 100644 index 2b92462fa92..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_access_fpreg.c +++ /dev/null @@ -1,121 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - Copyright (C) 2010 Konstantin Belousov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UPT_internal.h" - -#if HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE -int -_UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - unw_word_t *wp = (unw_word_t *) val; - struct UPT_info *ui = arg; - pid_t pid = ui->pid; - int i; - - if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) - return -UNW_EBADREG; - - errno = 0; - if (write) - for (i = 0; i < (int) (sizeof (*val) / sizeof (wp[i])); ++i) - { -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - ptrace (PTRACE_POKEUSER, pid, _UPT_reg_offset[reg] + i * sizeof(wp[i]), - wp[i]); -#endif - if (errno) - return -UNW_EBADREG; - } - else - for (i = 0; i < (int) (sizeof (*val) / sizeof (wp[i])); ++i) - { -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - wp[i] = ptrace (PTRACE_PEEKUSER, pid, - _UPT_reg_offset[reg] + i * sizeof(wp[i]), 0); -#endif - if (errno) - return -UNW_EBADREG; - } - return 0; -} -#elif HAVE_DECL_PT_GETFPREGS -int -_UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - struct UPT_info *ui = arg; - pid_t pid = ui->pid; - fpregset_t fpreg; - -#if defined(__amd64__) - if (1) /* XXXKIB */ - return -UNW_EBADREG; -#elif defined(__i386__) - if ((unsigned) reg < UNW_X86_ST0 || (unsigned) reg > UNW_X86_ST7) - return -UNW_EBADREG; -#elif defined(__arm__) - if ((unsigned) reg < UNW_ARM_F0 || (unsigned) reg > UNW_ARM_F7) - return -UNW_EBADREG; -#else -#error Fix me -#endif - if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) - return -UNW_EBADREG; - - if (ptrace(PT_GETFPREGS, pid, (caddr_t)&fpreg, 0) == -1) - return -UNW_EBADREG; - if (write) { -#if defined(__amd64__) - memcpy(&fpreg.fpr_xacc[reg], val, sizeof(unw_fpreg_t)); -#elif defined(__i386__) - memcpy(&fpreg.fpr_acc[reg], val, sizeof(unw_fpreg_t)); -#elif defined(__arm__) - memcpy(&fpreg.fpr[reg], val, sizeof(unw_fpreg_t)); -#else -#error Fix me -#endif - if (ptrace(PT_SETFPREGS, pid, (caddr_t)&fpreg, 0) == -1) - return -UNW_EBADREG; - } else -#if defined(__amd64__) - memcpy(val, &fpreg.fpr_xacc[reg], sizeof(unw_fpreg_t)); -#elif defined(__i386__) - memcpy(val, &fpreg.fpr_acc[reg], sizeof(unw_fpreg_t)); -#elif defined(__arm__) - memcpy(val, &fpreg.fpr[reg], sizeof(unw_fpreg_t)); -#else -#error Fix me -#endif - return 0; -} -#else -#error Fix me -#endif diff --git a/contrib/libunwind/src/ptrace/_UPT_access_mem.c b/contrib/libunwind/src/ptrace/_UPT_access_mem.c deleted file mode 100644 index 79bde25dffc..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_access_mem.c +++ /dev/null @@ -1,123 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - Copyright (C) 2010 Konstantin Belousov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UPT_internal.h" - -#if HAVE_DECL_PTRACE_POKEDATA || HAVE_TTRACE -int -_UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, - int write, void *arg) -{ - struct UPT_info *ui = arg; - int i, end; - unw_word_t tmp_val; - - if (!ui) - return -UNW_EINVAL; - - pid_t pid = ui->pid; - - // Some 32-bit archs have to define a 64-bit unw_word_t. - // Callers of this function therefore expect a 64-bit - // return value, but ptrace only returns a 32-bit value - // in such cases. - if (sizeof(long) == 4 && sizeof(unw_word_t) == 8) - end = 2; - else - end = 1; - - for (i = 0; i < end; i++) - { - unw_word_t tmp_addr = i == 0 ? addr : addr + 4; - - errno = 0; - if (write) - { -#if __BYTE_ORDER == __LITTLE_ENDIAN - tmp_val = i == 0 ? *val : *val >> 32; -#else - tmp_val = i == 0 && end == 2 ? *val >> 32 : *val; -#endif - - Debug (16, "mem[%lx] <- %lx\n", (long) tmp_addr, (long) tmp_val); -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - ptrace (PTRACE_POKEDATA, pid, tmp_addr, tmp_val); - if (errno) - return -UNW_EINVAL; -#endif - } - else - { -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - tmp_val = (unsigned long) ptrace (PTRACE_PEEKDATA, pid, tmp_addr, 0); - - if (i == 0) - *val = 0; - -#if __BYTE_ORDER == __LITTLE_ENDIAN - *val |= tmp_val << (i * 32); -#else - *val |= i == 0 && end == 2 ? tmp_val << 32 : tmp_val; -#endif - - if (errno) - return -UNW_EINVAL; -#endif - Debug (16, "mem[%lx] -> %lx\n", (long) tmp_addr, (long) tmp_val); - } - } - return 0; -} -#elif HAVE_DECL_PT_IO -int -_UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, - int write, void *arg) -{ - struct UPT_info *ui = arg; - if (!ui) - return -UNW_EINVAL; - pid_t pid = ui->pid; - struct ptrace_io_desc iod; - - iod.piod_offs = (void *)addr; - iod.piod_addr = val; - iod.piod_len = sizeof(*val); - iod.piod_op = write ? PIOD_WRITE_D : PIOD_READ_D; - if (write) - Debug (16, "mem[%lx] <- %lx\n", (long) addr, (long) *val); - if (ptrace(PT_IO, pid, (caddr_t)&iod, 0) == -1) - return -UNW_EINVAL; - if (!write) - Debug (16, "mem[%lx] -> %lx\n", (long) addr, (long) *val); - return 0; -} -#else -#error Fix me -#endif diff --git a/contrib/libunwind/src/ptrace/_UPT_access_reg.c b/contrib/libunwind/src/ptrace/_UPT_access_reg.c deleted file mode 100644 index ce25c783b04..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_access_reg.c +++ /dev/null @@ -1,352 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - Copyright (C) 2010 Konstantin Belousov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UPT_internal.h" - -#if UNW_TARGET_IA64 -# include -# ifdef HAVE_ASM_PTRACE_OFFSETS_H -# include -# endif -# include "tdep-ia64/rse.h" -#endif - -#if HAVE_DECL_PTRACE_SETREGSET -#include -int -_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, - int write, void *arg) -{ - struct UPT_info *ui = arg; - pid_t pid = ui->pid; - gregset_t regs; - char *r; - struct iovec loc; - -#if UNW_DEBUG - Debug(16, "using getregset: reg: %s [%u], val: %lx, write: %u\n", - unw_regname(reg), (unsigned) reg, (long) val, write); - - if (write) - Debug (16, "%s [%u] <- %lx\n", unw_regname (reg), (unsigned) reg, (long) *val); -#endif - if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) - { - errno = EINVAL; - goto badreg; - } - - loc.iov_base = ®s; - loc.iov_len = sizeof(regs); - - r = (char *)®s + _UPT_reg_offset[reg]; - if (ptrace (PTRACE_GETREGSET, pid, NT_PRSTATUS, &loc) == -1) - goto badreg; - if (write) { - memcpy(r, val, sizeof(unw_word_t)); - if (ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &loc) == -1) - goto badreg; - } else - memcpy(val, r, sizeof(unw_word_t)); - return 0; - -badreg: - Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno)); - return -UNW_EBADREG; -} -#elif HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE -int -_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, - int write, void *arg) -{ - struct UPT_info *ui = arg; - pid_t pid = ui->pid; - -#if UNW_DEBUG - Debug(16, "using pokeuser: reg: %s [%u], val: %lx, write: %d\n", unw_regname(reg), (unsigned) reg, (long) val, write); - - if (write) - Debug (16, "%s <- %lx\n", unw_regname (reg), (long) *val); -#endif - -#if UNW_TARGET_IA64 - if ((unsigned) reg - UNW_IA64_NAT < 32) - { - unsigned long nat_bits, mask; - - /* The Linux ptrace represents the statc NaT bits as a single word. */ - mask = ((unw_word_t) 1) << (reg - UNW_IA64_NAT); - errno = 0; -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - nat_bits = ptrace (PTRACE_PEEKUSER, pid, PT_NAT_BITS, 0); - if (errno) - goto badreg; -#endif - - if (write) - { - if (*val) - nat_bits |= mask; - else - nat_bits &= ~mask; -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - errno = 0; - ptrace (PTRACE_POKEUSER, pid, PT_NAT_BITS, nat_bits); - if (errno) - goto badreg; -#endif - } - goto out; - } - else - switch (reg) - { - case UNW_IA64_GR + 0: - if (write) - goto badreg; - *val = 0; - return 0; - - case UNW_REG_IP: - { - unsigned long ip, psr; - - /* distribute bundle-addr. & slot-number across PT_IIP & PT_IPSR. */ -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - errno = 0; - psr = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IPSR, 0); - if (errno) - goto badreg; -#endif - if (write) - { - ip = *val & ~0xfUL; - psr = (psr & ~0x3UL << 41) | (*val & 0x3); -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - errno = 0; - ptrace (PTRACE_POKEUSER, pid, PT_CR_IIP, ip); - ptrace (PTRACE_POKEUSER, pid, PT_CR_IPSR, psr); - if (errno) - goto badreg; -#endif - } - else - { -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - errno = 0; - ip = ptrace (PTRACE_PEEKUSER, pid, PT_CR_IIP, 0); - if (errno) - goto badreg; -#endif - *val = ip + ((psr >> 41) & 0x3); - } - goto out; - } - - case UNW_IA64_AR_BSPSTORE: - reg = UNW_IA64_AR_BSP; - break; - - case UNW_IA64_AR_BSP: - case UNW_IA64_BSP: - { - unsigned long sof, cfm, bsp; - -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - /* Account for the fact that ptrace() expects bsp to point - _after_ the current register frame. */ - errno = 0; - cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0); - if (errno) - goto badreg; -#endif - sof = (cfm & 0x7f); - - if (write) - { - bsp = rse_skip_regs (*val, sof); -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - errno = 0; - ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, bsp); - if (errno) - goto badreg; -#endif - } - else - { -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - errno = 0; - bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0); - if (errno) - goto badreg; -#endif - *val = rse_skip_regs (bsp, -sof); - } - goto out; - } - - case UNW_IA64_CFM: - /* If we change CFM, we need to adjust ptrace's notion of bsp - accordingly, so that the real bsp remains unchanged. */ - if (write) - { - unsigned long new_sof, old_sof, cfm, bsp; - -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - errno = 0; - bsp = ptrace (PTRACE_PEEKUSER, pid, PT_AR_BSP, 0); - cfm = ptrace (PTRACE_PEEKUSER, pid, PT_CFM, 0); -#endif - if (errno) - goto badreg; - old_sof = (cfm & 0x7f); - new_sof = (*val & 0x7f); - if (old_sof != new_sof) - { - bsp = rse_skip_regs (bsp, -old_sof + new_sof); -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - errno = 0; - ptrace (PTRACE_POKEUSER, pid, PT_AR_BSP, 0); - if (errno) - goto badreg; -#endif - } -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - errno = 0; - ptrace (PTRACE_POKEUSER, pid, PT_CFM, *val); - if (errno) - goto badreg; -#endif - goto out; - } - break; - } -#endif /* End of IA64 */ - - if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) - { -#if UNW_DEBUG - Debug(2, "register out of range: >= %zu / %zu\n", sizeof(_UPT_reg_offset), sizeof(_UPT_reg_offset[0])); -#endif - errno = EINVAL; - goto badreg; - } - -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#else - errno = 0; - if (write) - ptrace (PTRACE_POKEUSER, pid, _UPT_reg_offset[reg], *val); - else { -#if UNW_DEBUG - Debug(16, "ptrace PEEKUSER pid: %lu , reg: %lu , offs: %lu\n", (unsigned long)pid, (unsigned long)reg, - (unsigned long)_UPT_reg_offset[reg]); -#endif - *val = ptrace (PTRACE_PEEKUSER, pid, _UPT_reg_offset[reg], 0); - } - if (errno) { -#if UNW_DEBUG - Debug(2, "ptrace failure\n"); -#endif - goto badreg; - } -#endif - -#ifdef UNW_TARGET_IA64 - out: -#endif -#if UNW_DEBUG - if (!write) - Debug (16, "%s[%u] -> %lx\n", unw_regname (reg), (unsigned) reg, (long) *val); -#endif - return 0; - - badreg: - Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno)); - return -UNW_EBADREG; -} -#elif HAVE_DECL_PT_GETREGS -int -_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, - int write, void *arg) -{ - struct UPT_info *ui = arg; - pid_t pid = ui->pid; - gregset_t regs; - char *r; - -#if UNW_DEBUG - Debug(16, "using getregs: reg: %s [%u], val: %lx, write: %u\n", unw_regname(reg), (unsigned) reg, (long) val, write); - - if (write) - Debug (16, "%s [%u] <- %lx\n", unw_regname (reg), (unsigned) reg, (long) *val); -#endif - if ((unsigned) reg >= ARRAY_SIZE (_UPT_reg_offset)) - { - errno = EINVAL; - goto badreg; - } - r = (char *)®s + _UPT_reg_offset[reg]; - if (ptrace(PT_GETREGS, pid, (caddr_t)®s, 0) == -1) - goto badreg; - if (write) { - memcpy(r, val, sizeof(unw_word_t)); - if (ptrace(PT_SETREGS, pid, (caddr_t)®s, 0) == -1) - goto badreg; - } else - memcpy(val, r, sizeof(unw_word_t)); - return 0; - - badreg: - Debug (1, "bad register %s [%u] (error: %s)\n", unw_regname(reg), reg, strerror (errno)); - return -UNW_EBADREG; -} -#else -#error Port me -#endif diff --git a/contrib/libunwind/src/ptrace/_UPT_accessors.c b/contrib/libunwind/src/ptrace/_UPT_accessors.c deleted file mode 100644 index 3190e7894af..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_accessors.c +++ /dev/null @@ -1,38 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UPT_internal.h" - -PROTECTED unw_accessors_t _UPT_accessors = - { - .find_proc_info = _UPT_find_proc_info, - .put_unwind_info = _UPT_put_unwind_info, - .get_dyn_info_list_addr = _UPT_get_dyn_info_list_addr, - .access_mem = _UPT_access_mem, - .access_reg = _UPT_access_reg, - .access_fpreg = _UPT_access_fpreg, - .resume = _UPT_resume, - .get_proc_name = _UPT_get_proc_name - }; diff --git a/contrib/libunwind/src/ptrace/_UPT_create.c b/contrib/libunwind/src/ptrace/_UPT_create.c deleted file mode 100644 index dd59e974a7e..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_create.c +++ /dev/null @@ -1,46 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "_UPT_internal.h" - -void * -_UPT_create (pid_t pid) -{ - struct UPT_info *ui = malloc (sizeof (struct UPT_info)); - - if (!ui) - return NULL; - - memset (ui, 0, sizeof (*ui)); - ui->pid = pid; - ui->edi.di_cache.format = -1; - ui->edi.di_debug.format = -1; -#if UNW_TARGET_IA64 - ui->edi.ktab.format = -1; -#endif - return ui; -} diff --git a/contrib/libunwind/src/ptrace/_UPT_destroy.c b/contrib/libunwind/src/ptrace/_UPT_destroy.c deleted file mode 100644 index edb664ce123..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_destroy.c +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UPT_internal.h" - -void -_UPT_destroy (void *ptr) -{ - struct UPT_info *ui = (struct UPT_info *) ptr; - invalidate_edi (&ui->edi); - free (ptr); -} diff --git a/contrib/libunwind/src/ptrace/_UPT_elf.c b/contrib/libunwind/src/ptrace/_UPT_elf.c deleted file mode 100644 index efc43b578ba..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_elf.c +++ /dev/null @@ -1,5 +0,0 @@ -/* We need to get a separate copy of the ELF-code into - libunwind-ptrace since it cannot (and must not) have any ELF - dependencies on libunwind. */ -#include "libunwind_i.h" /* get ELFCLASS defined */ -#include "../elfxx.c" diff --git a/contrib/libunwind/src/ptrace/_UPT_find_proc_info.c b/contrib/libunwind/src/ptrace/_UPT_find_proc_info.c deleted file mode 100644 index b3209f451ea..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_find_proc_info.c +++ /dev/null @@ -1,145 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include -#include -#include - -#include - -#include "_UPT_internal.h" - -static int -get_unwind_info (struct elf_dyn_info *edi, pid_t pid, unw_addr_space_t as, unw_word_t ip) -{ - unsigned long segbase, mapoff; - char path[PATH_MAX]; - -#if UNW_TARGET_IA64 && defined(__linux) - if (!edi->ktab.start_ip && _Uia64_get_kernel_table (&edi->ktab) < 0) - return -UNW_ENOINFO; - - if (edi->ktab.format != -1 && ip >= edi->ktab.start_ip && ip < edi->ktab.end_ip) - return 0; -#endif - - if ((edi->di_cache.format != -1 - && ip >= edi->di_cache.start_ip && ip < edi->di_cache.end_ip) -#if UNW_TARGET_ARM - || (edi->di_debug.format != -1 - && ip >= edi->di_arm.start_ip && ip < edi->di_arm.end_ip) -#endif - || (edi->di_debug.format != -1 - && ip >= edi->di_debug.start_ip && ip < edi->di_debug.end_ip)) - return 0; - - invalidate_edi(edi); - - if (tdep_get_elf_image (&edi->ei, pid, ip, &segbase, &mapoff, path, - sizeof(path)) < 0) - return -UNW_ENOINFO; - - /* Here, SEGBASE is the starting-address of the (mmap'ped) segment - which covers the IP we're looking for. */ - if (tdep_find_unwind_table (edi, as, path, segbase, mapoff, ip) < 0) - return -UNW_ENOINFO; - - /* This can happen in corner cases where dynamically generated - code falls into the same page that contains the data-segment - and the page-offset of the code is within the first page of - the executable. */ - if (edi->di_cache.format != -1 - && (ip < edi->di_cache.start_ip || ip >= edi->di_cache.end_ip)) - edi->di_cache.format = -1; - - if (edi->di_debug.format != -1 - && (ip < edi->di_debug.start_ip || ip >= edi->di_debug.end_ip)) - edi->di_debug.format = -1; - - if (edi->di_cache.format == -1 -#if UNW_TARGET_ARM - && edi->di_arm.format == -1 -#endif - && edi->di_debug.format == -1) - return -UNW_ENOINFO; - - return 0; -} - -int -_UPT_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, - int need_unwind_info, void *arg) -{ - struct UPT_info *ui = arg; - int ret = -UNW_ENOINFO; - - if (get_unwind_info (&ui->edi, ui->pid, as, ip) < 0) - return -UNW_ENOINFO; - -#if UNW_TARGET_IA64 - if (ui->edi.ktab.format != -1) - { - /* The kernel unwind table resides in local memory, so we have - to use the local address space to search it. Since - _UPT_put_unwind_info() has no easy way of detecting this - case, we simply make a copy of the unwind-info, so - _UPT_put_unwind_info() can always free() the unwind-info - without ill effects. */ - ret = tdep_search_unwind_table (unw_local_addr_space, ip, &ui->edi.ktab, pi, - need_unwind_info, arg); - if (ret >= 0) - { - if (!need_unwind_info) - pi->unwind_info = NULL; - else - { - void *mem = malloc (pi->unwind_info_size); - - if (!mem) - return -UNW_ENOMEM; - memcpy (mem, pi->unwind_info, pi->unwind_info_size); - pi->unwind_info = mem; - } - } - } -#endif - - if (ret == -UNW_ENOINFO && ui->edi.di_cache.format != -1) - ret = tdep_search_unwind_table (as, ip, &ui->edi.di_cache, - pi, need_unwind_info, arg); - - if (ret == -UNW_ENOINFO && ui->edi.di_debug.format != -1) - ret = tdep_search_unwind_table (as, ip, &ui->edi.di_debug, pi, - need_unwind_info, arg); - -#if UNW_TARGET_ARM - if (ret == -UNW_ENOINFO && ui->edi.di_arm.format != -1) - ret = tdep_search_unwind_table (as, ip, &ui->edi.di_arm, pi, - need_unwind_info, arg); -#endif - - return ret; -} diff --git a/contrib/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c b/contrib/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c deleted file mode 100644 index cc5ed044186..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_get_dyn_info_list_addr.c +++ /dev/null @@ -1,105 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UPT_internal.h" - -#if UNW_TARGET_IA64 && defined(__linux) -# include "elf64.h" -# include "os-linux.h" - -static inline int -get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg, - int *countp) -{ - unsigned long lo, hi, off; - struct UPT_info *ui = arg; - struct map_iterator mi; - char path[PATH_MAX]; - unw_word_t res; - int count = 0; - - maps_init (&mi, ui->pid); - while (maps_next (&mi, &lo, &hi, &off)) - { - if (off) - continue; - - invalidate_edi(&ui->edi); - - if (elf_map_image (&ui->edi.ei, path) < 0) - /* ignore unmappable stuff like "/SYSV00001b58 (deleted)" */ - continue; - - Debug (16, "checking object %s\n", path); - - if (tdep_find_unwind_table (&ui->edi, as, path, lo, off, 0) > 0) - { - res = _Uia64_find_dyn_list (as, &ui->edi.di_cache, arg); - if (res && count++ == 0) - { - Debug (12, "dyn_info_list_addr = 0x%lx\n", (long) res); - *dil_addr = res; - } - } - } - maps_close (&mi); - *countp = count; - return 0; -} - -#else - -static inline int -get_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, void *arg, - int *countp) -{ -# warning Implement get_list_addr(), please. - *countp = 0; - return 0; -} - -#endif - -int -_UPT_get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dil_addr, - void *arg) -{ - int count, ret; - - Debug (12, "looking for dyn_info list\n"); - - if ((ret = get_list_addr (as, dil_addr, arg, &count)) < 0) - return ret; - - /* If multiple dynamic-info list addresses are found, we would have - to determine which was is the one actually in use (since the - dynamic name resolution algorithm will pick one "winner"). - Perhaps we'd have to track them all until we find one that's - non-empty. Hopefully, this case simply will never arise, since - only libunwind defines the dynamic info list head. */ - assert (count <= 1); - - return (count > 0) ? 0 : -UNW_ENOINFO; -} diff --git a/contrib/libunwind/src/ptrace/_UPT_get_proc_name.c b/contrib/libunwind/src/ptrace/_UPT_get_proc_name.c deleted file mode 100644 index 79c1f38e256..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_get_proc_name.c +++ /dev/null @@ -1,42 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Copyright (C) 2007 David Mosberger-Tang - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UPT_internal.h" - -int -_UPT_get_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, void *arg) -{ - struct UPT_info *ui = arg; - -#if ELF_CLASS == ELFCLASS64 - return _Uelf64_get_proc_name (as, ui->pid, ip, buf, buf_len, offp); -#elif ELF_CLASS == ELFCLASS32 - return _Uelf32_get_proc_name (as, ui->pid, ip, buf, buf_len, offp); -#else - return -UNW_ENOINFO; -#endif -} diff --git a/contrib/libunwind/src/ptrace/_UPT_internal.h b/contrib/libunwind/src/ptrace/_UPT_internal.h deleted file mode 100644 index 5cef2573ee6..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_internal.h +++ /dev/null @@ -1,59 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef _UPT_internal_h -#define _UPT_internal_h - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_PTRACE_H -#include -#endif -#ifdef HAVE_SYS_PROCFS_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "libunwind_i.h" - -struct UPT_info - { - pid_t pid; /* the process-id of the child we're unwinding */ - struct elf_dyn_info edi; - }; - -extern const int _UPT_reg_offset[UNW_REG_LAST + 1]; - -#endif /* _UPT_internal_h */ diff --git a/contrib/libunwind/src/ptrace/_UPT_put_unwind_info.c b/contrib/libunwind/src/ptrace/_UPT_put_unwind_info.c deleted file mode 100644 index d4b84631476..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_put_unwind_info.c +++ /dev/null @@ -1,35 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UPT_internal.h" - -void -_UPT_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *pi, void *arg) -{ - if (!pi->unwind_info) - return; - free (pi->unwind_info); - pi->unwind_info = NULL; -} diff --git a/contrib/libunwind/src/ptrace/_UPT_reg_offset.c b/contrib/libunwind/src/ptrace/_UPT_reg_offset.c deleted file mode 100644 index c82d1c98872..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_reg_offset.c +++ /dev/null @@ -1,638 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - Copyright (C) 2013 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UPT_internal.h" - -#include - -#ifdef HAVE_ASM_PTRACE_OFFSETS_H -# include -#endif - -const int _UPT_reg_offset[UNW_REG_LAST + 1] = - { -#ifdef HAVE_ASM_PTRACE_OFFSETS_H -# ifndef PT_AR_CSD -# define PT_AR_CSD -1 /* this was introduced with rev 2.1 of ia64 */ -# endif - - [UNW_IA64_GR + 0] = -1, [UNW_IA64_GR + 1] = PT_R1, - [UNW_IA64_GR + 2] = PT_R2, [UNW_IA64_GR + 3] = PT_R3, - [UNW_IA64_GR + 4] = PT_R4, [UNW_IA64_GR + 5] = PT_R5, - [UNW_IA64_GR + 6] = PT_R6, [UNW_IA64_GR + 7] = PT_R7, - [UNW_IA64_GR + 8] = PT_R8, [UNW_IA64_GR + 9] = PT_R9, - [UNW_IA64_GR + 10] = PT_R10, [UNW_IA64_GR + 11] = PT_R11, - [UNW_IA64_GR + 12] = PT_R12, [UNW_IA64_GR + 13] = PT_R13, - [UNW_IA64_GR + 14] = PT_R14, [UNW_IA64_GR + 15] = PT_R15, - [UNW_IA64_GR + 16] = PT_R16, [UNW_IA64_GR + 17] = PT_R17, - [UNW_IA64_GR + 18] = PT_R18, [UNW_IA64_GR + 19] = PT_R19, - [UNW_IA64_GR + 20] = PT_R20, [UNW_IA64_GR + 21] = PT_R21, - [UNW_IA64_GR + 22] = PT_R22, [UNW_IA64_GR + 23] = PT_R23, - [UNW_IA64_GR + 24] = PT_R24, [UNW_IA64_GR + 25] = PT_R25, - [UNW_IA64_GR + 26] = PT_R26, [UNW_IA64_GR + 27] = PT_R27, - [UNW_IA64_GR + 28] = PT_R28, [UNW_IA64_GR + 29] = PT_R29, - [UNW_IA64_GR + 30] = PT_R30, [UNW_IA64_GR + 31] = PT_R31, - - [UNW_IA64_NAT+ 0] = -1, [UNW_IA64_NAT+ 1] = PT_NAT_BITS, - [UNW_IA64_NAT+ 2] = PT_NAT_BITS, [UNW_IA64_NAT+ 3] = PT_NAT_BITS, - [UNW_IA64_NAT+ 4] = PT_NAT_BITS, [UNW_IA64_NAT+ 5] = PT_NAT_BITS, - [UNW_IA64_NAT+ 6] = PT_NAT_BITS, [UNW_IA64_NAT+ 7] = PT_NAT_BITS, - [UNW_IA64_NAT+ 8] = PT_NAT_BITS, [UNW_IA64_NAT+ 9] = PT_NAT_BITS, - [UNW_IA64_NAT+ 10] = PT_NAT_BITS, [UNW_IA64_NAT+ 11] = PT_NAT_BITS, - [UNW_IA64_NAT+ 12] = PT_NAT_BITS, [UNW_IA64_NAT+ 13] = PT_NAT_BITS, - [UNW_IA64_NAT+ 14] = PT_NAT_BITS, [UNW_IA64_NAT+ 15] = PT_NAT_BITS, - [UNW_IA64_NAT+ 16] = PT_NAT_BITS, [UNW_IA64_NAT+ 17] = PT_NAT_BITS, - [UNW_IA64_NAT+ 18] = PT_NAT_BITS, [UNW_IA64_NAT+ 19] = PT_NAT_BITS, - [UNW_IA64_NAT+ 20] = PT_NAT_BITS, [UNW_IA64_NAT+ 21] = PT_NAT_BITS, - [UNW_IA64_NAT+ 22] = PT_NAT_BITS, [UNW_IA64_NAT+ 23] = PT_NAT_BITS, - [UNW_IA64_NAT+ 24] = PT_NAT_BITS, [UNW_IA64_NAT+ 25] = PT_NAT_BITS, - [UNW_IA64_NAT+ 26] = PT_NAT_BITS, [UNW_IA64_NAT+ 27] = PT_NAT_BITS, - [UNW_IA64_NAT+ 28] = PT_NAT_BITS, [UNW_IA64_NAT+ 29] = PT_NAT_BITS, - [UNW_IA64_NAT+ 30] = PT_NAT_BITS, [UNW_IA64_NAT+ 31] = PT_NAT_BITS, - - [UNW_IA64_FR + 0] = -1, [UNW_IA64_FR + 1] = -1, - [UNW_IA64_FR + 2] = PT_F2, [UNW_IA64_FR + 3] = PT_F3, - [UNW_IA64_FR + 4] = PT_F4, [UNW_IA64_FR + 5] = PT_F5, - [UNW_IA64_FR + 6] = PT_F6, [UNW_IA64_FR + 7] = PT_F7, - [UNW_IA64_FR + 8] = PT_F8, [UNW_IA64_FR + 9] = PT_F9, - [UNW_IA64_FR + 10] = PT_F10, [UNW_IA64_FR + 11] = PT_F11, - [UNW_IA64_FR + 12] = PT_F12, [UNW_IA64_FR + 13] = PT_F13, - [UNW_IA64_FR + 14] = PT_F14, [UNW_IA64_FR + 15] = PT_F15, - [UNW_IA64_FR + 16] = PT_F16, [UNW_IA64_FR + 17] = PT_F17, - [UNW_IA64_FR + 18] = PT_F18, [UNW_IA64_FR + 19] = PT_F19, - [UNW_IA64_FR + 20] = PT_F20, [UNW_IA64_FR + 21] = PT_F21, - [UNW_IA64_FR + 22] = PT_F22, [UNW_IA64_FR + 23] = PT_F23, - [UNW_IA64_FR + 24] = PT_F24, [UNW_IA64_FR + 25] = PT_F25, - [UNW_IA64_FR + 26] = PT_F26, [UNW_IA64_FR + 27] = PT_F27, - [UNW_IA64_FR + 28] = PT_F28, [UNW_IA64_FR + 29] = PT_F29, - [UNW_IA64_FR + 30] = PT_F30, [UNW_IA64_FR + 31] = PT_F31, - [UNW_IA64_FR + 32] = PT_F32, [UNW_IA64_FR + 33] = PT_F33, - [UNW_IA64_FR + 34] = PT_F34, [UNW_IA64_FR + 35] = PT_F35, - [UNW_IA64_FR + 36] = PT_F36, [UNW_IA64_FR + 37] = PT_F37, - [UNW_IA64_FR + 38] = PT_F38, [UNW_IA64_FR + 39] = PT_F39, - [UNW_IA64_FR + 40] = PT_F40, [UNW_IA64_FR + 41] = PT_F41, - [UNW_IA64_FR + 42] = PT_F42, [UNW_IA64_FR + 43] = PT_F43, - [UNW_IA64_FR + 44] = PT_F44, [UNW_IA64_FR + 45] = PT_F45, - [UNW_IA64_FR + 46] = PT_F46, [UNW_IA64_FR + 47] = PT_F47, - [UNW_IA64_FR + 48] = PT_F48, [UNW_IA64_FR + 49] = PT_F49, - [UNW_IA64_FR + 50] = PT_F50, [UNW_IA64_FR + 51] = PT_F51, - [UNW_IA64_FR + 52] = PT_F52, [UNW_IA64_FR + 53] = PT_F53, - [UNW_IA64_FR + 54] = PT_F54, [UNW_IA64_FR + 55] = PT_F55, - [UNW_IA64_FR + 56] = PT_F56, [UNW_IA64_FR + 57] = PT_F57, - [UNW_IA64_FR + 58] = PT_F58, [UNW_IA64_FR + 59] = PT_F59, - [UNW_IA64_FR + 60] = PT_F60, [UNW_IA64_FR + 61] = PT_F61, - [UNW_IA64_FR + 62] = PT_F62, [UNW_IA64_FR + 63] = PT_F63, - [UNW_IA64_FR + 64] = PT_F64, [UNW_IA64_FR + 65] = PT_F65, - [UNW_IA64_FR + 66] = PT_F66, [UNW_IA64_FR + 67] = PT_F67, - [UNW_IA64_FR + 68] = PT_F68, [UNW_IA64_FR + 69] = PT_F69, - [UNW_IA64_FR + 70] = PT_F70, [UNW_IA64_FR + 71] = PT_F71, - [UNW_IA64_FR + 72] = PT_F72, [UNW_IA64_FR + 73] = PT_F73, - [UNW_IA64_FR + 74] = PT_F74, [UNW_IA64_FR + 75] = PT_F75, - [UNW_IA64_FR + 76] = PT_F76, [UNW_IA64_FR + 77] = PT_F77, - [UNW_IA64_FR + 78] = PT_F78, [UNW_IA64_FR + 79] = PT_F79, - [UNW_IA64_FR + 80] = PT_F80, [UNW_IA64_FR + 81] = PT_F81, - [UNW_IA64_FR + 82] = PT_F82, [UNW_IA64_FR + 83] = PT_F83, - [UNW_IA64_FR + 84] = PT_F84, [UNW_IA64_FR + 85] = PT_F85, - [UNW_IA64_FR + 86] = PT_F86, [UNW_IA64_FR + 87] = PT_F87, - [UNW_IA64_FR + 88] = PT_F88, [UNW_IA64_FR + 89] = PT_F89, - [UNW_IA64_FR + 90] = PT_F90, [UNW_IA64_FR + 91] = PT_F91, - [UNW_IA64_FR + 92] = PT_F92, [UNW_IA64_FR + 93] = PT_F93, - [UNW_IA64_FR + 94] = PT_F94, [UNW_IA64_FR + 95] = PT_F95, - [UNW_IA64_FR + 96] = PT_F96, [UNW_IA64_FR + 97] = PT_F97, - [UNW_IA64_FR + 98] = PT_F98, [UNW_IA64_FR + 99] = PT_F99, - [UNW_IA64_FR +100] = PT_F100, [UNW_IA64_FR +101] = PT_F101, - [UNW_IA64_FR +102] = PT_F102, [UNW_IA64_FR +103] = PT_F103, - [UNW_IA64_FR +104] = PT_F104, [UNW_IA64_FR +105] = PT_F105, - [UNW_IA64_FR +106] = PT_F106, [UNW_IA64_FR +107] = PT_F107, - [UNW_IA64_FR +108] = PT_F108, [UNW_IA64_FR +109] = PT_F109, - [UNW_IA64_FR +110] = PT_F110, [UNW_IA64_FR +111] = PT_F111, - [UNW_IA64_FR +112] = PT_F112, [UNW_IA64_FR +113] = PT_F113, - [UNW_IA64_FR +114] = PT_F114, [UNW_IA64_FR +115] = PT_F115, - [UNW_IA64_FR +116] = PT_F116, [UNW_IA64_FR +117] = PT_F117, - [UNW_IA64_FR +118] = PT_F118, [UNW_IA64_FR +119] = PT_F119, - [UNW_IA64_FR +120] = PT_F120, [UNW_IA64_FR +121] = PT_F121, - [UNW_IA64_FR +122] = PT_F122, [UNW_IA64_FR +123] = PT_F123, - [UNW_IA64_FR +124] = PT_F124, [UNW_IA64_FR +125] = PT_F125, - [UNW_IA64_FR +126] = PT_F126, [UNW_IA64_FR +127] = PT_F127, - - [UNW_IA64_AR + 0] = -1, [UNW_IA64_AR + 1] = -1, - [UNW_IA64_AR + 2] = -1, [UNW_IA64_AR + 3] = -1, - [UNW_IA64_AR + 4] = -1, [UNW_IA64_AR + 5] = -1, - [UNW_IA64_AR + 6] = -1, [UNW_IA64_AR + 7] = -1, - [UNW_IA64_AR + 8] = -1, [UNW_IA64_AR + 9] = -1, - [UNW_IA64_AR + 10] = -1, [UNW_IA64_AR + 11] = -1, - [UNW_IA64_AR + 12] = -1, [UNW_IA64_AR + 13] = -1, - [UNW_IA64_AR + 14] = -1, [UNW_IA64_AR + 15] = -1, - [UNW_IA64_AR + 16] = PT_AR_RSC, [UNW_IA64_AR + 17] = PT_AR_BSP, - [UNW_IA64_AR + 18] = PT_AR_BSPSTORE,[UNW_IA64_AR + 19] = PT_AR_RNAT, - [UNW_IA64_AR + 20] = -1, [UNW_IA64_AR + 21] = -1, - [UNW_IA64_AR + 22] = -1, [UNW_IA64_AR + 23] = -1, - [UNW_IA64_AR + 24] = -1, [UNW_IA64_AR + 25] = PT_AR_CSD, - [UNW_IA64_AR + 26] = -1, [UNW_IA64_AR + 27] = -1, - [UNW_IA64_AR + 28] = -1, [UNW_IA64_AR + 29] = -1, - [UNW_IA64_AR + 30] = -1, [UNW_IA64_AR + 31] = -1, - [UNW_IA64_AR + 32] = PT_AR_CCV, [UNW_IA64_AR + 33] = -1, - [UNW_IA64_AR + 34] = -1, [UNW_IA64_AR + 35] = -1, - [UNW_IA64_AR + 36] = PT_AR_UNAT, [UNW_IA64_AR + 37] = -1, - [UNW_IA64_AR + 38] = -1, [UNW_IA64_AR + 39] = -1, - [UNW_IA64_AR + 40] = PT_AR_FPSR, [UNW_IA64_AR + 41] = -1, - [UNW_IA64_AR + 42] = -1, [UNW_IA64_AR + 43] = -1, - [UNW_IA64_AR + 44] = -1, [UNW_IA64_AR + 45] = -1, - [UNW_IA64_AR + 46] = -1, [UNW_IA64_AR + 47] = -1, - [UNW_IA64_AR + 48] = -1, [UNW_IA64_AR + 49] = -1, - [UNW_IA64_AR + 50] = -1, [UNW_IA64_AR + 51] = -1, - [UNW_IA64_AR + 52] = -1, [UNW_IA64_AR + 53] = -1, - [UNW_IA64_AR + 54] = -1, [UNW_IA64_AR + 55] = -1, - [UNW_IA64_AR + 56] = -1, [UNW_IA64_AR + 57] = -1, - [UNW_IA64_AR + 58] = -1, [UNW_IA64_AR + 59] = -1, - [UNW_IA64_AR + 60] = -1, [UNW_IA64_AR + 61] = -1, - [UNW_IA64_AR + 62] = -1, [UNW_IA64_AR + 63] = -1, - [UNW_IA64_AR + 64] = PT_AR_PFS, [UNW_IA64_AR + 65] = PT_AR_LC, - [UNW_IA64_AR + 66] = PT_AR_EC, [UNW_IA64_AR + 67] = -1, - [UNW_IA64_AR + 68] = -1, [UNW_IA64_AR + 69] = -1, - [UNW_IA64_AR + 70] = -1, [UNW_IA64_AR + 71] = -1, - [UNW_IA64_AR + 72] = -1, [UNW_IA64_AR + 73] = -1, - [UNW_IA64_AR + 74] = -1, [UNW_IA64_AR + 75] = -1, - [UNW_IA64_AR + 76] = -1, [UNW_IA64_AR + 77] = -1, - [UNW_IA64_AR + 78] = -1, [UNW_IA64_AR + 79] = -1, - [UNW_IA64_AR + 80] = -1, [UNW_IA64_AR + 81] = -1, - [UNW_IA64_AR + 82] = -1, [UNW_IA64_AR + 83] = -1, - [UNW_IA64_AR + 84] = -1, [UNW_IA64_AR + 85] = -1, - [UNW_IA64_AR + 86] = -1, [UNW_IA64_AR + 87] = -1, - [UNW_IA64_AR + 88] = -1, [UNW_IA64_AR + 89] = -1, - [UNW_IA64_AR + 90] = -1, [UNW_IA64_AR + 91] = -1, - [UNW_IA64_AR + 92] = -1, [UNW_IA64_AR + 93] = -1, - [UNW_IA64_AR + 94] = -1, [UNW_IA64_AR + 95] = -1, - [UNW_IA64_AR + 96] = -1, [UNW_IA64_AR + 97] = -1, - [UNW_IA64_AR + 98] = -1, [UNW_IA64_AR + 99] = -1, - [UNW_IA64_AR +100] = -1, [UNW_IA64_AR +101] = -1, - [UNW_IA64_AR +102] = -1, [UNW_IA64_AR +103] = -1, - [UNW_IA64_AR +104] = -1, [UNW_IA64_AR +105] = -1, - [UNW_IA64_AR +106] = -1, [UNW_IA64_AR +107] = -1, - [UNW_IA64_AR +108] = -1, [UNW_IA64_AR +109] = -1, - [UNW_IA64_AR +110] = -1, [UNW_IA64_AR +111] = -1, - [UNW_IA64_AR +112] = -1, [UNW_IA64_AR +113] = -1, - [UNW_IA64_AR +114] = -1, [UNW_IA64_AR +115] = -1, - [UNW_IA64_AR +116] = -1, [UNW_IA64_AR +117] = -1, - [UNW_IA64_AR +118] = -1, [UNW_IA64_AR +119] = -1, - [UNW_IA64_AR +120] = -1, [UNW_IA64_AR +121] = -1, - [UNW_IA64_AR +122] = -1, [UNW_IA64_AR +123] = -1, - [UNW_IA64_AR +124] = -1, [UNW_IA64_AR +125] = -1, - [UNW_IA64_AR +126] = -1, [UNW_IA64_AR +127] = -1, - - [UNW_IA64_BR + 0] = PT_B0, [UNW_IA64_BR + 1] = PT_B1, - [UNW_IA64_BR + 2] = PT_B2, [UNW_IA64_BR + 3] = PT_B3, - [UNW_IA64_BR + 4] = PT_B4, [UNW_IA64_BR + 5] = PT_B5, - [UNW_IA64_BR + 6] = PT_B6, [UNW_IA64_BR + 7] = PT_B7, - - [UNW_IA64_PR] = PT_PR, - [UNW_IA64_CFM] = PT_CFM, - [UNW_IA64_IP] = PT_CR_IIP -#elif defined(HAVE_TTRACE) -# warning No support for ttrace() yet. -#elif defined(UNW_TARGET_HPPA) - [UNW_HPPA_GR + 0] = 0x000, [UNW_HPPA_GR + 1] = 0x004, - [UNW_HPPA_GR + 2] = 0x008, [UNW_HPPA_GR + 3] = 0x00c, - [UNW_HPPA_GR + 4] = 0x010, [UNW_HPPA_GR + 5] = 0x014, - [UNW_HPPA_GR + 6] = 0x018, [UNW_HPPA_GR + 7] = 0x01c, - [UNW_HPPA_GR + 8] = 0x020, [UNW_HPPA_GR + 9] = 0x024, - [UNW_HPPA_GR + 10] = 0x028, [UNW_HPPA_GR + 11] = 0x02c, - [UNW_HPPA_GR + 12] = 0x030, [UNW_HPPA_GR + 13] = 0x034, - [UNW_HPPA_GR + 14] = 0x038, [UNW_HPPA_GR + 15] = 0x03c, - [UNW_HPPA_GR + 16] = 0x040, [UNW_HPPA_GR + 17] = 0x044, - [UNW_HPPA_GR + 18] = 0x048, [UNW_HPPA_GR + 19] = 0x04c, - [UNW_HPPA_GR + 20] = 0x050, [UNW_HPPA_GR + 21] = 0x054, - [UNW_HPPA_GR + 22] = 0x058, [UNW_HPPA_GR + 23] = 0x05c, - [UNW_HPPA_GR + 24] = 0x060, [UNW_HPPA_GR + 25] = 0x064, - [UNW_HPPA_GR + 26] = 0x068, [UNW_HPPA_GR + 27] = 0x06c, - [UNW_HPPA_GR + 28] = 0x070, [UNW_HPPA_GR + 29] = 0x074, - [UNW_HPPA_GR + 30] = 0x078, [UNW_HPPA_GR + 31] = 0x07c, - - [UNW_HPPA_FR + 0] = 0x080, [UNW_HPPA_FR + 1] = 0x088, - [UNW_HPPA_FR + 2] = 0x090, [UNW_HPPA_FR + 3] = 0x098, - [UNW_HPPA_FR + 4] = 0x0a0, [UNW_HPPA_FR + 5] = 0x0a8, - [UNW_HPPA_FR + 6] = 0x0b0, [UNW_HPPA_FR + 7] = 0x0b8, - [UNW_HPPA_FR + 8] = 0x0c0, [UNW_HPPA_FR + 9] = 0x0c8, - [UNW_HPPA_FR + 10] = 0x0d0, [UNW_HPPA_FR + 11] = 0x0d8, - [UNW_HPPA_FR + 12] = 0x0e0, [UNW_HPPA_FR + 13] = 0x0e8, - [UNW_HPPA_FR + 14] = 0x0f0, [UNW_HPPA_FR + 15] = 0x0f8, - [UNW_HPPA_FR + 16] = 0x100, [UNW_HPPA_FR + 17] = 0x108, - [UNW_HPPA_FR + 18] = 0x110, [UNW_HPPA_FR + 19] = 0x118, - [UNW_HPPA_FR + 20] = 0x120, [UNW_HPPA_FR + 21] = 0x128, - [UNW_HPPA_FR + 22] = 0x130, [UNW_HPPA_FR + 23] = 0x138, - [UNW_HPPA_FR + 24] = 0x140, [UNW_HPPA_FR + 25] = 0x148, - [UNW_HPPA_FR + 26] = 0x150, [UNW_HPPA_FR + 27] = 0x158, - [UNW_HPPA_FR + 28] = 0x160, [UNW_HPPA_FR + 29] = 0x168, - [UNW_HPPA_FR + 30] = 0x170, [UNW_HPPA_FR + 31] = 0x178, - - [UNW_HPPA_IP] = 0x1a8 /* IAOQ[0] */ -#elif defined(UNW_TARGET_X86) -#if defined __FreeBSD__ -#define UNW_R_OFF(R, r) \ - [UNW_X86_##R] = offsetof(gregset_t, r_##r), - UNW_R_OFF(EAX, eax) - UNW_R_OFF(EDX, edx) - UNW_R_OFF(ECX, ecx) - UNW_R_OFF(EBX, ebx) - UNW_R_OFF(ESI, esi) - UNW_R_OFF(EDI, edi) - UNW_R_OFF(EBP, ebp) - UNW_R_OFF(ESP, esp) - UNW_R_OFF(EIP, eip) -// UNW_R_OFF(CS, cs) -// UNW_R_OFF(EFLAGS, eflags) -// UNW_R_OFF(SS, ss) -#elif defined __linux__ - [UNW_X86_EAX] = 0x18, - [UNW_X86_EBX] = 0x00, - [UNW_X86_ECX] = 0x04, - [UNW_X86_EDX] = 0x08, - [UNW_X86_ESI] = 0x0c, - [UNW_X86_EDI] = 0x10, - [UNW_X86_EBP] = 0x14, - [UNW_X86_EIP] = 0x30, - [UNW_X86_ESP] = 0x3c -/* CS = 0x34, */ -/* DS = 0x1c, */ -/* ES = 0x20, */ -/* FS = 0x24, */ -/* GS = 0x28, */ -/* ORIG_EAX = 0x2c, */ -/* EFLAGS = 0x38, */ -/* SS = 0x40 */ -#else -#error Port me -#endif -#elif defined(UNW_TARGET_X86_64) -#if defined __FreeBSD__ -#define UNW_R_OFF(R, r) \ - [UNW_X86_64_##R] = offsetof(gregset_t, r_##r), - UNW_R_OFF(RAX, rax) - UNW_R_OFF(RDX, rdx) - UNW_R_OFF(RCX, rcx) - UNW_R_OFF(RBX, rbx) - UNW_R_OFF(RSI, rsi) - UNW_R_OFF(RDI, rdi) - UNW_R_OFF(RBP, rbp) - UNW_R_OFF(RSP, rsp) - UNW_R_OFF(R8, r8) - UNW_R_OFF(R9, r9) - UNW_R_OFF(R10, r10) - UNW_R_OFF(R11, r11) - UNW_R_OFF(R12, r12) - UNW_R_OFF(R13, r13) - UNW_R_OFF(R14, r14) - UNW_R_OFF(R15, r15) - UNW_R_OFF(RIP, rip) -// UNW_R_OFF(CS, cs) -// UNW_R_OFF(EFLAGS, rflags) -// UNW_R_OFF(SS, ss) -#undef UNW_R_OFF -#elif defined __linux__ - [UNW_X86_64_RAX] = 0x50, - [UNW_X86_64_RDX] = 0x60, - [UNW_X86_64_RCX] = 0x58, - [UNW_X86_64_RBX] = 0x28, - [UNW_X86_64_RSI] = 0x68, - [UNW_X86_64_RDI] = 0x70, - [UNW_X86_64_RBP] = 0x20, - [UNW_X86_64_RSP] = 0x98, - [UNW_X86_64_R8] = 0x48, - [UNW_X86_64_R9] = 0x40, - [UNW_X86_64_R10] = 0x38, - [UNW_X86_64_R11] = 0x30, - [UNW_X86_64_R12] = 0x18, - [UNW_X86_64_R13] = 0x10, - [UNW_X86_64_R14] = 0x08, - [UNW_X86_64_R15] = 0x00, - [UNW_X86_64_RIP] = 0x80 -// [UNW_X86_64_CS] = 0x88, -// [UNW_X86_64_EFLAGS] = 0x90, -// [UNW_X86_64_RSP] = 0x98, -// [UNW_X86_64_SS] = 0xa0 -#else -#error Port me -#endif -#elif defined(UNW_TARGET_PPC32) || defined(UNW_TARGET_PPC64) - -#define UNW_REG_SLOT_SIZE sizeof(unsigned long) -#define UNW_PPC_R(v) ((v) * UNW_REG_SLOT_SIZE) -#define UNW_PPC_PT(p) UNW_PPC_R(PT_##p) - -#define UNW_FP_OFF(b, i) \ - [UNW_PPC##b##_F##i] = UNW_PPC_R(PT_FPR0 + i * 8/UNW_REG_SLOT_SIZE) - -#define UNW_R_OFF(b, i) \ - [UNW_PPC##b##_R##i] = UNW_PPC_R(PT_R##i) - -#define UNW_PPC_REGS(b) \ - UNW_R_OFF(b, 0), \ - UNW_R_OFF(b, 1), \ - UNW_R_OFF(b, 2), \ - UNW_R_OFF(b, 3), \ - UNW_R_OFF(b, 4), \ - UNW_R_OFF(b, 5), \ - UNW_R_OFF(b, 6), \ - UNW_R_OFF(b, 7), \ - UNW_R_OFF(b, 8), \ - UNW_R_OFF(b, 9), \ - UNW_R_OFF(b, 10), \ - UNW_R_OFF(b, 11), \ - UNW_R_OFF(b, 12), \ - UNW_R_OFF(b, 13), \ - UNW_R_OFF(b, 14), \ - UNW_R_OFF(b, 15), \ - UNW_R_OFF(b, 16), \ - UNW_R_OFF(b, 17), \ - UNW_R_OFF(b, 18), \ - UNW_R_OFF(b, 19), \ - UNW_R_OFF(b, 20), \ - UNW_R_OFF(b, 21), \ - UNW_R_OFF(b, 22), \ - UNW_R_OFF(b, 23), \ - UNW_R_OFF(b, 24), \ - UNW_R_OFF(b, 25), \ - UNW_R_OFF(b, 26), \ - UNW_R_OFF(b, 27), \ - UNW_R_OFF(b, 28), \ - UNW_R_OFF(b, 29), \ - UNW_R_OFF(b, 30), \ - UNW_R_OFF(b, 31), \ - \ - [UNW_PPC##b##_CTR] = UNW_PPC_PT(CTR), \ - [UNW_PPC##b##_XER] = UNW_PPC_PT(XER), \ - [UNW_PPC##b##_LR] = UNW_PPC_PT(LNK), \ - \ - UNW_FP_OFF(b, 0), \ - UNW_FP_OFF(b, 1), \ - UNW_FP_OFF(b, 2), \ - UNW_FP_OFF(b, 3), \ - UNW_FP_OFF(b, 4), \ - UNW_FP_OFF(b, 5), \ - UNW_FP_OFF(b, 6), \ - UNW_FP_OFF(b, 7), \ - UNW_FP_OFF(b, 8), \ - UNW_FP_OFF(b, 9), \ - UNW_FP_OFF(b, 10), \ - UNW_FP_OFF(b, 11), \ - UNW_FP_OFF(b, 12), \ - UNW_FP_OFF(b, 13), \ - UNW_FP_OFF(b, 14), \ - UNW_FP_OFF(b, 15), \ - UNW_FP_OFF(b, 16), \ - UNW_FP_OFF(b, 17), \ - UNW_FP_OFF(b, 18), \ - UNW_FP_OFF(b, 19), \ - UNW_FP_OFF(b, 20), \ - UNW_FP_OFF(b, 21), \ - UNW_FP_OFF(b, 22), \ - UNW_FP_OFF(b, 23), \ - UNW_FP_OFF(b, 24), \ - UNW_FP_OFF(b, 25), \ - UNW_FP_OFF(b, 26), \ - UNW_FP_OFF(b, 27), \ - UNW_FP_OFF(b, 28), \ - UNW_FP_OFF(b, 29), \ - UNW_FP_OFF(b, 30), \ - UNW_FP_OFF(b, 31) - -#define UNW_PPC32_REGS \ - [UNW_PPC32_FPSCR] = UNW_PPC_PT(FPSCR), \ - [UNW_PPC32_CCR] = UNW_PPC_PT(CCR) - -#define UNW_VR_OFF(i) \ - [UNW_PPC64_V##i] = UNW_PPC_R(PT_VR0 + i * 2) - -#define UNW_PPC64_REGS \ - [UNW_PPC64_NIP] = UNW_PPC_PT(NIP), \ - [UNW_PPC64_FRAME_POINTER] = -1, \ - [UNW_PPC64_ARG_POINTER] = -1, \ - [UNW_PPC64_CR0] = -1, \ - [UNW_PPC64_CR1] = -1, \ - [UNW_PPC64_CR2] = -1, \ - [UNW_PPC64_CR3] = -1, \ - [UNW_PPC64_CR4] = -1, \ - [UNW_PPC64_CR5] = -1, \ - [UNW_PPC64_CR6] = -1, \ - [UNW_PPC64_CR7] = -1, \ - [UNW_PPC64_VRSAVE] = UNW_PPC_PT(VRSAVE), \ - [UNW_PPC64_VSCR] = UNW_PPC_PT(VSCR), \ - [UNW_PPC64_SPE_ACC] = -1, \ - [UNW_PPC64_SPEFSCR] = -1, \ - UNW_VR_OFF(0), \ - UNW_VR_OFF(1), \ - UNW_VR_OFF(2), \ - UNW_VR_OFF(3), \ - UNW_VR_OFF(4), \ - UNW_VR_OFF(5), \ - UNW_VR_OFF(6), \ - UNW_VR_OFF(7), \ - UNW_VR_OFF(8), \ - UNW_VR_OFF(9), \ - UNW_VR_OFF(10), \ - UNW_VR_OFF(11), \ - UNW_VR_OFF(12), \ - UNW_VR_OFF(13), \ - UNW_VR_OFF(14), \ - UNW_VR_OFF(15), \ - UNW_VR_OFF(16), \ - UNW_VR_OFF(17), \ - UNW_VR_OFF(18), \ - UNW_VR_OFF(19), \ - UNW_VR_OFF(20), \ - UNW_VR_OFF(21), \ - UNW_VR_OFF(22), \ - UNW_VR_OFF(23), \ - UNW_VR_OFF(24), \ - UNW_VR_OFF(25), \ - UNW_VR_OFF(26), \ - UNW_VR_OFF(27), \ - UNW_VR_OFF(28), \ - UNW_VR_OFF(29), \ - UNW_VR_OFF(30), \ - UNW_VR_OFF(31) - -#if defined(UNW_TARGET_PPC32) - UNW_PPC_REGS(32), - UNW_PPC32_REGS, -#else - UNW_PPC_REGS(64), - UNW_PPC64_REGS, -#endif - -#elif defined(UNW_TARGET_ARM) -#if defined(__linux__) || defined(__FreeBSD__) - [UNW_ARM_R0] = 0x00, - [UNW_ARM_R1] = 0x04, - [UNW_ARM_R2] = 0x08, - [UNW_ARM_R3] = 0x0c, - [UNW_ARM_R4] = 0x10, - [UNW_ARM_R5] = 0x14, - [UNW_ARM_R6] = 0x18, - [UNW_ARM_R7] = 0x1c, - [UNW_ARM_R8] = 0x20, - [UNW_ARM_R9] = 0x24, - [UNW_ARM_R10] = 0x28, - [UNW_ARM_R11] = 0x2c, - [UNW_ARM_R12] = 0x30, - [UNW_ARM_R13] = 0x34, - [UNW_ARM_R14] = 0x38, - [UNW_ARM_R15] = 0x3c, -#else -#error Fix me -#endif -#elif defined(UNW_TARGET_MIPS) - [UNW_MIPS_R0] = 0, - [UNW_MIPS_R1] = 1, - [UNW_MIPS_R2] = 2, - [UNW_MIPS_R3] = 3, - [UNW_MIPS_R4] = 4, - [UNW_MIPS_R5] = 5, - [UNW_MIPS_R6] = 6, - [UNW_MIPS_R7] = 7, - [UNW_MIPS_R8] = 8, - [UNW_MIPS_R9] = 9, - [UNW_MIPS_R10] = 10, - [UNW_MIPS_R11] = 11, - [UNW_MIPS_R12] = 12, - [UNW_MIPS_R13] = 13, - [UNW_MIPS_R14] = 14, - [UNW_MIPS_R15] = 15, - [UNW_MIPS_R16] = 16, - [UNW_MIPS_R17] = 17, - [UNW_MIPS_R18] = 18, - [UNW_MIPS_R19] = 19, - [UNW_MIPS_R20] = 20, - [UNW_MIPS_R21] = 21, - [UNW_MIPS_R22] = 22, - [UNW_MIPS_R23] = 23, - [UNW_MIPS_R24] = 24, - [UNW_MIPS_R25] = 25, - [UNW_MIPS_R26] = 26, - [UNW_MIPS_R27] = 27, - [UNW_MIPS_R28] = 28, - [UNW_MIPS_R29] = 29, - [UNW_MIPS_R30] = 30, - [UNW_MIPS_R31] = 31, - [UNW_MIPS_PC] = 64, -#elif defined(UNW_TARGET_SH) -#elif defined(UNW_TARGET_AARCH64) - [UNW_AARCH64_X0] = 0x00, - [UNW_AARCH64_X1] = 0x08, - [UNW_AARCH64_X2] = 0x10, - [UNW_AARCH64_X3] = 0x18, - [UNW_AARCH64_X4] = 0x20, - [UNW_AARCH64_X5] = 0x28, - [UNW_AARCH64_X6] = 0x30, - [UNW_AARCH64_X7] = 0x38, - [UNW_AARCH64_X8] = 0x40, - [UNW_AARCH64_X9] = 0x48, - [UNW_AARCH64_X10] = 0x50, - [UNW_AARCH64_X11] = 0x58, - [UNW_AARCH64_X12] = 0x60, - [UNW_AARCH64_X13] = 0x68, - [UNW_AARCH64_X14] = 0x70, - [UNW_AARCH64_X15] = 0x78, - [UNW_AARCH64_X16] = 0x80, - [UNW_AARCH64_X17] = 0x88, - [UNW_AARCH64_X18] = 0x90, - [UNW_AARCH64_X19] = 0x98, - [UNW_AARCH64_X20] = 0xa0, - [UNW_AARCH64_X21] = 0xa8, - [UNW_AARCH64_X22] = 0xb0, - [UNW_AARCH64_X23] = 0xb8, - [UNW_AARCH64_X24] = 0xc0, - [UNW_AARCH64_X25] = 0xc8, - [UNW_AARCH64_X26] = 0xd0, - [UNW_AARCH64_X27] = 0xd8, - [UNW_AARCH64_X28] = 0xe0, - [UNW_AARCH64_X29] = 0xe8, - [UNW_AARCH64_X30] = 0xf0, - [UNW_AARCH64_SP] = 0xf8, - [UNW_AARCH64_PC] = 0x100, - [UNW_AARCH64_PSTATE] = 0x108 -#elif defined(UNW_TARGET_TILEGX) - [UNW_TILEGX_R0] = 0x00, - [UNW_TILEGX_R1] = 0x08, - [UNW_TILEGX_R2] = 0x10, - [UNW_TILEGX_R3] = 0x08, - [UNW_TILEGX_R4] = 0x20, - [UNW_TILEGX_R5] = 0x28, - [UNW_TILEGX_R6] = 0x30, - [UNW_TILEGX_R7] = 0x38, - [UNW_TILEGX_R8] = 0x40, - [UNW_TILEGX_R9] = 0x48, - [UNW_TILEGX_R10] = 0x50, - [UNW_TILEGX_R11] = 0x58, - [UNW_TILEGX_R12] = 0x60, - [UNW_TILEGX_R13] = 0x68, - [UNW_TILEGX_R14] = 0x70, - [UNW_TILEGX_R15] = 0x78, - [UNW_TILEGX_R16] = 0x80, - [UNW_TILEGX_R17] = 0x88, - [UNW_TILEGX_R18] = 0x90, - [UNW_TILEGX_R19] = 0x98, - [UNW_TILEGX_R20] = 0xa0, - [UNW_TILEGX_R21] = 0xa8, - [UNW_TILEGX_R22] = 0xb0, - [UNW_TILEGX_R23] = 0xb8, - [UNW_TILEGX_R24] = 0xc0, - [UNW_TILEGX_R25] = 0xc8, - [UNW_TILEGX_R26] = 0xd0, - [UNW_TILEGX_R27] = 0xd8, - [UNW_TILEGX_R28] = 0xe0, - [UNW_TILEGX_R29] = 0xe8, - [UNW_TILEGX_R30] = 0xf0, - [UNW_TILEGX_R31] = 0xf8, - [UNW_TILEGX_R32] = 0x100, - [UNW_TILEGX_R33] = 0x108, - [UNW_TILEGX_R34] = 0x110, - [UNW_TILEGX_R35] = 0x118, - [UNW_TILEGX_R36] = 0x120, - [UNW_TILEGX_R37] = 0x128, - [UNW_TILEGX_R38] = 0x130, - [UNW_TILEGX_R39] = 0x138, - [UNW_TILEGX_R40] = 0x140, - [UNW_TILEGX_R41] = 0x148, - [UNW_TILEGX_R42] = 0x150, - [UNW_TILEGX_R43] = 0x158, - [UNW_TILEGX_R44] = 0x160, - [UNW_TILEGX_R45] = 0x168, - [UNW_TILEGX_R46] = 0x170, - [UNW_TILEGX_R47] = 0x178, - [UNW_TILEGX_R48] = 0x180, - [UNW_TILEGX_R49] = 0x188, - [UNW_TILEGX_R50] = 0x190, - [UNW_TILEGX_R51] = 0x198, - [UNW_TILEGX_R52] = 0x1a0, - [UNW_TILEGX_R53] = 0x1a8, - [UNW_TILEGX_R54] = 0x1b0, - [UNW_TILEGX_R55] = 0x1b8, - [UNW_TILEGX_PC] = 0x1a0 -#else -# error Fix me. -#endif - }; diff --git a/contrib/libunwind/src/ptrace/_UPT_resume.c b/contrib/libunwind/src/ptrace/_UPT_resume.c deleted file mode 100644 index d70a0d48218..00000000000 --- a/contrib/libunwind/src/ptrace/_UPT_resume.c +++ /dev/null @@ -1,40 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "_UPT_internal.h" - -int -_UPT_resume (unw_addr_space_t as, unw_cursor_t *c, void *arg) -{ - struct UPT_info *ui = arg; - -#ifdef HAVE_TTRACE -# warning No support for ttrace() yet. -#elif HAVE_DECL_PTRACE_CONT - return ptrace (PTRACE_CONT, ui->pid, 0, 0); -#elif HAVE_DECL_PT_CONTINUE - return ptrace(PT_CONTINUE, ui->pid, (caddr_t)1, 0); -#endif -} diff --git a/contrib/libunwind/src/ptrace/libunwind-ptrace.pc.in b/contrib/libunwind/src/ptrace/libunwind-ptrace.pc.in deleted file mode 100644 index 673004b69ef..00000000000 --- a/contrib/libunwind/src/ptrace/libunwind-ptrace.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libunwind-ptrace -Description: libunwind ptrace library -Version: @VERSION@ -Requires: libunwind-generic libunwind -Libs: -L${libdir} -lunwind-ptrace -Cflags: -I${includedir} diff --git a/contrib/libunwind/src/setjmp/libunwind-setjmp.pc.in b/contrib/libunwind/src/setjmp/libunwind-setjmp.pc.in deleted file mode 100644 index 7b71126535b..00000000000 --- a/contrib/libunwind/src/setjmp/libunwind-setjmp.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libunwind-setjmp -Description: libunwind setjmp library -Version: @VERSION@ -Requires: libunwind -Libs: -L${libdir} -lunwind-setjmp -Cflags: -I${includedir} diff --git a/contrib/libunwind/src/setjmp/longjmp.c b/contrib/libunwind/src/setjmp/longjmp.c deleted file mode 100644 index 8295a9b8ed4..00000000000 --- a/contrib/libunwind/src/setjmp/longjmp.c +++ /dev/null @@ -1,115 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#define UNW_LOCAL_ONLY - -#undef _FORTIFY_SOURCE -#include -#include -#include -#include -#include - -#include "jmpbuf.h" -#include "setjmp_i.h" - -#if defined(__GLIBC__) -#if __GLIBC_PREREQ(2, 4) - -/* Starting with glibc-2.4, {sig,}setjmp in GLIBC obfuscates the - register values in jmp_buf by XORing them with a "random" - canary value. - - This makes it impossible to implement longjmp, as we - can never match wp[JB_SP], unless we decode the canary first. - - Doing so is possible, but doesn't appear to be worth the trouble, - so we simply defer to glibc longjmp here. */ -#define _longjmp __nonworking__longjmp -#define longjmp __nonworking_longjmp -static void _longjmp (jmp_buf env, int val); -static void longjmp (jmp_buf env, int val); -#endif -#endif /* __GLIBC__ */ - -void -_longjmp (jmp_buf env, int val) -{ - extern int _UI_longjmp_cont; - unw_context_t uc; - unw_cursor_t c; - unw_word_t sp; - unw_word_t *wp = (unw_word_t *) env; - - if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0) - abort (); - - do - { - if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0) - abort (); -#ifdef __FreeBSD__ - if (sp != wp[JB_SP] + sizeof(unw_word_t)) -#else - if (sp != wp[JB_SP]) -#endif - continue; - - if (!bsp_match (&c, wp)) - continue; - - /* found the right frame: */ - - assert (UNW_NUM_EH_REGS >= 2); - - if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0 - || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0 - || unw_set_reg (&c, UNW_REG_IP, - (unw_word_t) (uintptr_t) &_UI_longjmp_cont)) - abort (); - - unw_resume (&c); - - abort (); - } - while (unw_step (&c) > 0); - - abort (); -} - -#ifdef __GNUC__ -#define STRINGIFY1(x) #x -#define STRINGIFY(x) STRINGIFY1(x) -void longjmp (jmp_buf env, int val) - __attribute__ ((alias (STRINGIFY(_longjmp)))); -#else - -void -longjmp (jmp_buf env, int val) -{ - _longjmp (env, val); -} - -#endif /* __GNUC__ */ diff --git a/contrib/libunwind/src/setjmp/setjmp.c b/contrib/libunwind/src/setjmp/setjmp.c deleted file mode 100644 index bec9fc7d5bf..00000000000 --- a/contrib/libunwind/src/setjmp/setjmp.c +++ /dev/null @@ -1,49 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "jmpbuf.h" - -/* Why use K&R syntax here? setjmp() is often a macro and that - expands into a call to, say, __setjmp() and we need to define the - libunwind-version of setjmp() with the name of the actual function. - Using K&R syntax lets us keep the setjmp() macro while keeping the - syntax valid... This trick works provided setjmp() doesn't do - anything other than a function call. */ - -int -setjmp (env) - jmp_buf env; -{ - void **wp = (void **) env; - - /* this should work on most platforms, but may not be - performance-optimal; check the code! */ - wp[JB_SP] = __builtin_frame_address (0); - wp[JB_RP] = (void *) __builtin_return_address (0); - return 0; -} diff --git a/contrib/libunwind/src/setjmp/setjmp_i.h b/contrib/libunwind/src/setjmp/setjmp_i.h deleted file mode 100644 index 4d9139693ec..00000000000 --- a/contrib/libunwind/src/setjmp/setjmp_i.h +++ /dev/null @@ -1,118 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#if UNW_TARGET_IA64 - -#include "libunwind_i.h" -#include "tdep-ia64/rse.h" - -static inline int -bsp_match (unw_cursor_t *c, unw_word_t *wp) -{ - unw_word_t bsp, pfs, sol; - - if (unw_get_reg (c, UNW_IA64_BSP, &bsp) < 0 - || unw_get_reg (c, UNW_IA64_AR_PFS, &pfs) < 0) - abort (); - - /* simulate the effect of "br.call sigsetjmp" on ar.bsp: */ - sol = (pfs >> 7) & 0x7f; - bsp = rse_skip_regs (bsp, sol); - - if (bsp != wp[JB_BSP]) - return 0; - - if (unlikely (sol == 0)) - { - unw_word_t sp, prev_sp; - unw_cursor_t tmp = *c; - - /* The caller of {sig,}setjmp() cannot have a NULL-frame. If we - see a NULL-frame, we haven't reached the right target yet. - To have a NULL-frame, the number of locals must be zero and - the stack-frame must also be empty. */ - - if (unw_step (&tmp) < 0) - abort (); - - if (unw_get_reg (&tmp, UNW_REG_SP, &sp) < 0 - || unw_get_reg (&tmp, UNW_REG_SP, &prev_sp) < 0) - abort (); - - if (sp == prev_sp) - /* got a NULL-frame; keep looking... */ - return 0; - } - return 1; -} - -/* On ia64 we cannot always call sigprocmask() at - _UI_siglongjmp_cont() because the signal may have switched stacks - and the old stack's register-backing store may have overflown, - leaving us no space to allocate the stacked registers needed to - call sigprocmask(). Fortunately, we can just let unw_resume() (via - sigreturn) take care of restoring the signal-mask. That's faster - anyhow. */ -static inline int -resume_restores_sigmask (unw_cursor_t *c, unw_word_t *wp) -{ - unw_word_t sc_addr = ((struct cursor *) c)->sigcontext_addr; - struct sigcontext *sc = (struct sigcontext *) sc_addr; - sigset_t current_mask; - void *mp; - - if (!sc_addr) - return 0; - - /* let unw_resume() install the desired signal mask */ - - if (wp[JB_MASK_SAVED]) - mp = &wp[JB_MASK]; - else - { - if (sigprocmask (SIG_BLOCK, NULL, ¤t_mask) < 0) - abort (); - mp = ¤t_mask; - } - memcpy (&sc->sc_mask, mp, sizeof (sc->sc_mask)); - return 1; -} - -#else /* !UNW_TARGET_IA64 */ - -static inline int -bsp_match (unw_cursor_t *c, unw_word_t *wp) -{ - return 1; -} - -static inline int -resume_restores_sigmask (unw_cursor_t *c, unw_word_t *wp) -{ - /* We may want to do this analogously as for ia64... */ - return 0; -} - -#endif /* !UNW_TARGET_IA64 */ diff --git a/contrib/libunwind/src/setjmp/siglongjmp.c b/contrib/libunwind/src/setjmp/siglongjmp.c deleted file mode 100644 index 0e286f6f085..00000000000 --- a/contrib/libunwind/src/setjmp/siglongjmp.c +++ /dev/null @@ -1,127 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#define UNW_LOCAL_ONLY - -#include - -#include "libunwind_i.h" -#include "jmpbuf.h" -#include "setjmp_i.h" - -#if !defined(_NSIG) && defined(_SIG_MAXSIG) -# define _NSIG (_SIG_MAXSIG - 1) -#endif - -#if defined(__GLIBC__) -#if __GLIBC_PREREQ(2, 4) - -/* Starting with glibc-2.4, {sig,}setjmp in GLIBC obfuscates the - register values in jmp_buf by XORing them with a "random" - canary value. - - This makes it impossible to implement longjmp, as we - can never match wp[JB_SP], unless we decode the canary first. - - Doing so is possible, but doesn't appear to be worth the trouble, - so we simply defer to glibc siglongjmp here. */ - -#define siglongjmp __nonworking_siglongjmp -static void siglongjmp (sigjmp_buf env, int val) UNUSED; -#endif -#endif /* __GLIBC_PREREQ */ - -void -siglongjmp (sigjmp_buf env, int val) -{ - unw_word_t *wp = (unw_word_t *) env; - extern int _UI_siglongjmp_cont; - extern int _UI_longjmp_cont; - unw_context_t uc; - unw_cursor_t c; - unw_word_t sp; - int *cont; - - if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0) - abort (); - - do - { - if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0) - abort (); -#ifdef __FreeBSD__ - if (sp != wp[JB_SP] + sizeof(unw_word_t)) -#else - if (sp != wp[JB_SP]) -#endif - continue; - - if (!bsp_match (&c, wp)) - continue; - - /* found the right frame: */ - - /* default to resuming without restoring signal-mask */ - cont = &_UI_longjmp_cont; - - /* Order of evaluation is important here: if unw_resume() - restores signal mask, we must set it up appropriately, even - if wp[JB_MASK_SAVED] is FALSE. */ - if (!resume_restores_sigmask (&c, wp) && wp[JB_MASK_SAVED]) - { - /* sigmask was saved */ -#if defined(__linux__) - if (UNW_NUM_EH_REGS < 4 || _NSIG > 16 * sizeof (unw_word_t)) - /* signal mask doesn't fit into EH arguments and we can't - put it on the stack without overwriting something - else... */ - abort (); - else - if (unw_set_reg (&c, UNW_REG_EH + 2, wp[JB_MASK]) < 0 - || (_NSIG > 8 * sizeof (unw_word_t) - && unw_set_reg (&c, UNW_REG_EH + 3, wp[JB_MASK + 1]) < 0)) - abort (); -#elif defined(__FreeBSD__) - if (unw_set_reg (&c, UNW_REG_EH + 2, &wp[JB_MASK]) < 0) - abort(); -#else -#error Port me -#endif - cont = &_UI_siglongjmp_cont; - } - - if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0 - || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0 - || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) cont)) - abort (); - - unw_resume (&c); - - abort (); - } - while (unw_step (&c) > 0); - - abort (); -} diff --git a/contrib/libunwind/src/setjmp/sigsetjmp.c b/contrib/libunwind/src/setjmp/sigsetjmp.c deleted file mode 100644 index f84935d638a..00000000000 --- a/contrib/libunwind/src/setjmp/sigsetjmp.c +++ /dev/null @@ -1,50 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include -#include - -#include "jmpbuf.h" - -int -sigsetjmp (sigjmp_buf env, int savemask) -{ - unw_word_t *wp = (unw_word_t *) env; - - /* This should work on most platforms, but may not be - performance-optimal; check the code! */ - - wp[JB_SP] = (unw_word_t) __builtin_frame_address (0); - wp[JB_RP] = (unw_word_t) __builtin_return_address (0); - wp[JB_MASK_SAVED] = savemask; - - /* Note: we assume here that "wp" has same or better alignment as - sigset_t. */ - if (savemask - && sigprocmask (SIG_BLOCK, NULL, (sigset_t *) (wp + JB_MASK)) < 0) - abort (); - return 0; -} diff --git a/contrib/libunwind/src/sh/Gapply_reg_state.c b/contrib/libunwind/src/sh/Gapply_reg_state.c deleted file mode 100644 index eec93046f56..00000000000 --- a/contrib/libunwind/src/sh/Gapply_reg_state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); -} diff --git a/contrib/libunwind/src/sh/Gcreate_addr_space.c b/contrib/libunwind/src/sh/Gcreate_addr_space.c deleted file mode 100644 index 1907d046726..00000000000 --- a/contrib/libunwind/src/sh/Gcreate_addr_space.c +++ /dev/null @@ -1,59 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "unwind_i.h" - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* SH supports little-endian and big-endian. */ - if (byte_order != 0 && byte_order != __LITTLE_ENDIAN - && byte_order != __BIG_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - /* Default to little-endian for SH. */ - if (byte_order == 0 || byte_order == __LITTLE_ENDIAN) - as->big_endian = 0; - else - as->big_endian = 1; - - return as; -#endif -} diff --git a/contrib/libunwind/src/sh/Gget_proc_info.c b/contrib/libunwind/src/sh/Gget_proc_info.c deleted file mode 100644 index de9199f9958..00000000000 --- a/contrib/libunwind/src/sh/Gget_proc_info.c +++ /dev/null @@ -1,39 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - ret = dwarf_make_proc_info (&c->dwarf); - if (ret < 0) - return ret; - - *pi = c->dwarf.pi; - return 0; -} diff --git a/contrib/libunwind/src/sh/Gget_save_loc.c b/contrib/libunwind/src/sh/Gget_save_loc.c deleted file mode 100644 index 7690a808719..00000000000 --- a/contrib/libunwind/src/sh/Gget_save_loc.c +++ /dev/null @@ -1,83 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) -{ - struct cursor *c = (struct cursor *) cursor; - dwarf_loc_t loc; - - switch (reg) - { - case UNW_SH_R0: - case UNW_SH_R1: - case UNW_SH_R2: - case UNW_SH_R3: - case UNW_SH_R4: - case UNW_SH_R5: - case UNW_SH_R6: - case UNW_SH_R7: - case UNW_SH_R8: - case UNW_SH_R9: - case UNW_SH_R10: - case UNW_SH_R11: - case UNW_SH_R12: - case UNW_SH_R13: - case UNW_SH_R14: - case UNW_SH_R15: - case UNW_SH_PC: - case UNW_SH_PR: - loc = c->dwarf.loc[reg]; - break; - - default: - loc = DWARF_NULL_LOC; /* default to "not saved" */ - break; - } - - memset (sloc, 0, sizeof (*sloc)); - - if (DWARF_IS_NULL_LOC (loc)) - { - sloc->type = UNW_SLT_NONE; - return 0; - } - -#if !defined(UNW_LOCAL_ONLY) - if (DWARF_IS_REG_LOC (loc)) - { - sloc->type = UNW_SLT_REG; - sloc->u.regnum = DWARF_GET_LOC (loc); - } - else -#endif - { - sloc->type = UNW_SLT_MEMORY; - sloc->u.addr = DWARF_GET_LOC (loc); - } - return 0; -} diff --git a/contrib/libunwind/src/sh/Gglobal.c b/contrib/libunwind/src/sh/Gglobal.c deleted file mode 100644 index ed273339768..00000000000 --- a/contrib/libunwind/src/sh/Gglobal.c +++ /dev/null @@ -1,56 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "dwarf_i.h" - -HIDDEN define_lock (sh_lock); -HIDDEN int tdep_init_done; - -HIDDEN void -tdep_init (void) -{ - intrmask_t saved_mask; - - sigfillset (&unwi_full_mask); - - lock_acquire (&sh_lock, saved_mask); - { - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - mi_init (); - - dwarf_init (); - -#ifndef UNW_REMOTE_ONLY - sh_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - } - out: - lock_release (&sh_lock, saved_mask); -} diff --git a/contrib/libunwind/src/sh/Ginit.c b/contrib/libunwind/src/sh/Ginit.c deleted file mode 100644 index 0bfac4907ee..00000000000 --- a/contrib/libunwind/src/sh/Ginit.c +++ /dev/null @@ -1,186 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -PROTECTED unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; - -static inline void * -uc_addr (ucontext_t *uc, int reg) -{ - if (reg >= UNW_SH_R0 && reg <= UNW_SH_PR) - return &uc->uc_mcontext.gregs[reg]; - else - return NULL; -} - -# ifdef UNW_LOCAL_ONLY - -HIDDEN void * -tdep_uc_addr (ucontext_t *uc, int reg) -{ - return uc_addr (uc, reg); -} - -# endif /* UNW_LOCAL_ONLY */ - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - -/* XXX fix me: there is currently no way to locate the dyn-info list - by a remote unwinder. On ia64, this is done via a special - unwind-table entry. Perhaps something similar can be done with - DWARF2 unwind info. */ - -static void -put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ - *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - if (write) - { - Debug (16, "mem[%x] <- %x\n", addr, *val); - *(unw_word_t *) addr = *val; - } - else - { - *val = *(unw_word_t *) addr; - Debug (16, "mem[%x] -> %x\n", addr, *val); - } - return 0; -} - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, - void *arg) -{ - unw_word_t *addr; - ucontext_t *uc = arg; - - if (unw_is_fpreg (reg)) - goto badreg; - - if (!(addr = uc_addr (uc, reg))) - goto badreg; - - if (write) - { - *(unw_word_t *) addr = *val; - Debug (12, "%s <- %x\n", unw_regname (reg), *val); - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "%s -> %x\n", unw_regname (reg), *val); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - ucontext_t *uc = arg; - unw_fpreg_t *addr; - - if (!unw_is_fpreg (reg)) - goto badreg; - - if (!(addr = uc_addr (uc, reg))) - goto badreg; - - if (write) - { - Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - *(unw_fpreg_t *) addr = *val; - } - else - { - *val = *(unw_fpreg_t *) addr; - Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - /* attempt to access a non-preserved register */ - return -UNW_EBADREG; -} - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp); -} - -HIDDEN void -sh_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; - local_addr_space.acc.find_proc_info = dwarf_find_proc_info; - local_addr_space.acc.put_unwind_info = put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = sh_local_resume; - local_addr_space.acc.get_proc_name = get_static_proc_name; - unw_flush_cache (&local_addr_space, 0, 0); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/sh/Ginit_local.c b/contrib/libunwind/src/sh/Ginit_local.c deleted file mode 100644 index 36d1329b6ff..00000000000 --- a/contrib/libunwind/src/sh/Ginit_local.c +++ /dev/null @@ -1,78 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright 2011 Linaro Limited - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "init.h" - -#ifdef UNW_REMOTE_ONLY - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) -{ - return -UNW_EINVAL; -} - -#else /* !UNW_REMOTE_ONLY */ - -static int -unw_init_local (unw_cursor_t *cursor, unw_context_t *uc, unsigned use_prev_instr) -{ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = unw_local_addr_space; - c->dwarf.as_arg = uc; - - return common_init (c, use_prev_instr); -} - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, unw_context_t *uc) -{ - return unw_init_local_common(cursor, uc, 1); -} - -PROTECTED int -unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) -{ - if (!flag) - { - return unw_init_local_common(cursor, uc, 1); - } - else if (flag == UNW_INIT_SIGNAL_FRAME) - { - return unw_init_local_common(cursor, uc, 0); - } - else - { - return -UNW_EINVAL; - } -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/sh/Ginit_remote.c b/contrib/libunwind/src/sh/Ginit_remote.c deleted file mode 100644 index f284e994f4b..00000000000 --- a/contrib/libunwind/src/sh/Ginit_remote.c +++ /dev/null @@ -1,45 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "init.h" -#include "unwind_i.h" - -PROTECTED int -unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) -{ -#ifdef UNW_LOCAL_ONLY - return -UNW_EINVAL; -#else /* !UNW_LOCAL_ONLY */ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = as; - c->dwarf.as_arg = as_arg; - return common_init (c, 0); -#endif /* !UNW_LOCAL_ONLY */ -} diff --git a/contrib/libunwind/src/sh/Gis_signal_frame.c b/contrib/libunwind/src/sh/Gis_signal_frame.c deleted file mode 100644 index 9719f8e0846..00000000000 --- a/contrib/libunwind/src/sh/Gis_signal_frame.c +++ /dev/null @@ -1,119 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -/* Disassembly of the Linux VDSO sigreturn functions: - -00000000 <__kernel_sigreturn>: - 0: 05 93 mov.w e <__kernel_sigreturn+0xe>,r3 ! 77 - 2: 10 c3 trapa #16 - 4: 0b 20 or r0,r0 - 6: 0b 20 or r0,r0 - 8: 0b 20 or r0,r0 - a: 0b 20 or r0,r0 - c: 0b 20 or r0,r0 - e: 77 00 .word 0x0077 - 10: 09 00 nop - 12: 09 00 nop - 14: 09 00 nop - 16: 09 00 nop - 18: 09 00 nop - 1a: 09 00 nop - 1c: 09 00 nop - 1e: 09 00 nop - -00000020 <__kernel_rt_sigreturn>: - 20: 05 93 mov.w 2e <__kernel_rt_sigreturn+0xe>,r3 ! ad - 22: 10 c3 trapa #16 - 24: 0b 20 or r0,r0 - 26: 0b 20 or r0,r0 - 28: 0b 20 or r0,r0 - 2a: 0b 20 or r0,r0 - 2c: 0b 20 or r0,r0 - 2e: ad 00 mov.w @(r0,r10),r0 - 30: 09 00 nop - 32: 09 00 nop - 34: 09 00 nop - 36: 09 00 nop - 38: 09 00 nop - 3a: 09 00 nop - 3c: 09 00 nop - 3e: 09 00 nop -*/ - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ -#ifdef __linux__ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - ip = c->dwarf.ip; - - ret = (*a->access_mem) (as, ip, &w0, 0, arg); - if (ret < 0) - return ret; - - if (w0 != 0xc3109305) - return 0; - - ret = (*a->access_mem) (as, ip+4, &w0, 0, arg); - if (ret < 0) - return ret; - - if (w0 != 0x200b200b) - return 0; - - ret = (*a->access_mem) (as, ip+8, &w0, 0, arg); - if (ret < 0) - return ret; - - if (w0 != 0x200b200b) - return 0; - - ret = (*a->access_mem) (as, ip+12, &w0, 0, arg); - if (ret < 0) - return ret; - - if (w0 == 0x0077200b) - return 1; /* non-RT */ - else if (w0 == 0x00ad200b) - return 2; /* RT */ - - /* does not look like a signal frame */ - return 0; - -#else - return -UNW_ENOINFO; -#endif -} diff --git a/contrib/libunwind/src/sh/Greg_states_iterate.c b/contrib/libunwind/src/sh/Greg_states_iterate.c deleted file mode 100644 index a39837a1781..00000000000 --- a/contrib/libunwind/src/sh/Greg_states_iterate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_reg_states_iterate (&c->dwarf, cb, token); -} diff --git a/contrib/libunwind/src/sh/Gregs.c b/contrib/libunwind/src/sh/Gregs.c deleted file mode 100644 index 7d8e8e93da0..00000000000 --- a/contrib/libunwind/src/sh/Gregs.c +++ /dev/null @@ -1,81 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - dwarf_loc_t loc = DWARF_NULL_LOC; - - switch (reg) - { - case UNW_SH_PC: - if (write) - c->dwarf.ip = *valp; /* update the IP cache */ - case UNW_SH_R0: - case UNW_SH_R1: - case UNW_SH_R2: - case UNW_SH_R3: - case UNW_SH_R4: - case UNW_SH_R5: - case UNW_SH_R6: - case UNW_SH_R7: - case UNW_SH_R8: - case UNW_SH_R9: - case UNW_SH_R10: - case UNW_SH_R11: - case UNW_SH_R12: - case UNW_SH_R13: - case UNW_SH_R14: - case UNW_SH_PR: - loc = c->dwarf.loc[reg]; - break; - - case UNW_SH_R15: - if (write) - return -UNW_EREADONLYREG; - *valp = c->dwarf.cfa; - return 0; - - default: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; - } - - if (write) - return dwarf_put (&c->dwarf, loc, *valp); - else - return dwarf_get (&c->dwarf, loc, valp); -} - -HIDDEN int -tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, - int write) -{ - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} diff --git a/contrib/libunwind/src/sh/Gresume.c b/contrib/libunwind/src/sh/Gresume.c deleted file mode 100644 index b14e419bdd3..00000000000 --- a/contrib/libunwind/src/sh/Gresume.c +++ /dev/null @@ -1,165 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright 2011 Linaro Limited - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" - -#ifndef UNW_REMOTE_ONLY - -HIDDEN inline int -sh_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ -#ifdef __linux__ - struct cursor *c = (struct cursor *) cursor; - unw_tdep_context_t *uc = c->dwarf.as_arg; - - if (c->sigcontext_format == SH_SCF_NONE) - { - /* Since there are no signals involved here we restore the non scratch - registers only. */ - unsigned long regs[8]; - regs[0] = uc->uc_mcontext.gregs[8]; - regs[1] = uc->uc_mcontext.gregs[9]; - regs[2] = uc->uc_mcontext.gregs[10]; - regs[3] = uc->uc_mcontext.gregs[11]; - regs[4] = uc->uc_mcontext.gregs[12]; - regs[5] = uc->uc_mcontext.gregs[13]; - regs[6] = uc->uc_mcontext.gregs[14]; - regs[7] = uc->uc_mcontext.gregs[15]; - unsigned long pc = uc->uc_mcontext.pr; - - struct regs_overlay { - char x[sizeof(regs)]; - }; - - asm volatile ( - "mov.l @%0+, r8\n" - "mov.l @%0+, r9\n" - "mov.l @%0+, r10\n" - "mov.l @%0+, r11\n" - "mov.l @%0+, r12\n" - "mov.l @%0+, r13\n" - "mov.l @%0+, r14\n" - "mov.l @%0, r15\n" - "lds %1, pr\n" - "rts\n" - "nop\n" - : - : "r" (regs), - "r" (pc), - "m" (*(struct regs_overlay *)regs) - ); - } - else - { - /* In case a signal frame is involved, we're using its trampoline which - calls sigreturn. */ - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - sc->sc_regs[0] = uc->uc_mcontext.gregs[0]; - sc->sc_regs[1] = uc->uc_mcontext.gregs[1]; - sc->sc_regs[2] = uc->uc_mcontext.gregs[2]; - sc->sc_regs[3] = uc->uc_mcontext.gregs[3]; - sc->sc_regs[4] = uc->uc_mcontext.gregs[4]; - sc->sc_regs[5] = uc->uc_mcontext.gregs[5]; - sc->sc_regs[6] = uc->uc_mcontext.gregs[6]; - sc->sc_regs[7] = uc->uc_mcontext.gregs[7]; - sc->sc_regs[8] = uc->uc_mcontext.gregs[8]; - sc->sc_regs[9] = uc->uc_mcontext.gregs[9]; - sc->sc_regs[10] = uc->uc_mcontext.gregs[10]; - sc->sc_regs[11] = uc->uc_mcontext.gregs[11]; - sc->sc_regs[12] = uc->uc_mcontext.gregs[12]; - sc->sc_regs[13] = uc->uc_mcontext.gregs[13]; - sc->sc_regs[14] = uc->uc_mcontext.gregs[14]; - sc->sc_regs[15] = uc->uc_mcontext.gregs[15]; - sc->sc_pc = uc->uc_mcontext.pc; - sc->sc_pr = uc->uc_mcontext.pr; - - /* Set the SP and the PC in order to continue execution at the modified - trampoline which restores the signal mask and the registers. */ - asm __volatile__ ( - "mov %0, r15\n" - "lds %1, pr\n" - "rts\n" - "nop\n" - : - : "r" (c->sigcontext_sp), - "r" (c->sigcontext_pc) - ); - } - unreachable(); -#endif - return -UNW_EINVAL; -} - -#endif /* !UNW_REMOTE_ONLY */ - -static inline void -establish_machine_state (struct cursor *c) -{ - unw_addr_space_t as = c->dwarf.as; - void *arg = c->dwarf.as_arg; - unw_fpreg_t fpval; - unw_word_t val; - int reg; - - Debug (8, "copying out cursor state\n"); - - for (reg = 0; reg <= UNW_REG_LAST; ++reg) - { - Debug (16, "copying %s %d\n", unw_regname (reg), reg); - if (unw_is_fpreg (reg)) - { - if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) - as->acc.access_fpreg (as, reg, &fpval, 1, arg); - } - else - { - if (tdep_access_reg (c, reg, &val, 0) >= 0) - as->acc.access_reg (as, reg, &val, 1, arg); - } - } -} - -PROTECTED int -unw_resume (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - - Debug (1, "(cursor=%p)\n", c); - - if (!c->dwarf.ip) - { - /* This can happen easily when the frame-chain gets truncated - due to bad or missing unwind-info. */ - Debug (1, "refusing to resume execution at address 0\n"); - return -UNW_EINVAL; - } - - establish_machine_state (c); - - return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, - c->dwarf.as_arg); -} diff --git a/contrib/libunwind/src/sh/Gstep.c b/contrib/libunwind/src/sh/Gstep.c deleted file mode 100644 index 9bbb8477fa1..00000000000 --- a/contrib/libunwind/src/sh/Gstep.c +++ /dev/null @@ -1,117 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright 2011 Linaro Limited - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" - -PROTECTED int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; - struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); - - if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) - return -UNW_EUNSPEC; - - ret = unw_is_signal_frame (cursor); - Debug(1, "unw_is_signal_frame()=%d\n", ret); - - /* Save the SP and PC to be able to return execution at this point - later in time (unw_resume). */ - c->sigcontext_sp = c->dwarf.cfa; - c->sigcontext_pc = c->dwarf.ip; - - if (ret == 1) - { - /* Handle non-RT signal frame. */ - c->sigcontext_format = SH_SCF_LINUX_SIGFRAME; - sc_addr = sp_addr; - } - else if (ret == 2) - { - /* Handle RT signal frame. */ - c->sigcontext_format = SH_SCF_LINUX_RT_SIGFRAME; - sc_addr = sp_addr + sizeof (siginfo_t) + LINUX_UC_MCONTEXT_OFF; - } - else - return -UNW_EUNSPEC; - - c->sigcontext_addr = sc_addr; - - /* Update the dwarf cursor. - Set the location of the registers to the corresponding addresses of the - uc_mcontext / sigcontext structure contents. */ - c->dwarf.loc[UNW_SH_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); - c->dwarf.loc[UNW_SH_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); - c->dwarf.loc[UNW_SH_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); - c->dwarf.loc[UNW_SH_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); - c->dwarf.loc[UNW_SH_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); - c->dwarf.loc[UNW_SH_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); - c->dwarf.loc[UNW_SH_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); - c->dwarf.loc[UNW_SH_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); - c->dwarf.loc[UNW_SH_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); - c->dwarf.loc[UNW_SH_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); - c->dwarf.loc[UNW_SH_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); - c->dwarf.loc[UNW_SH_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0); - c->dwarf.loc[UNW_SH_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0); - c->dwarf.loc[UNW_SH_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0); - c->dwarf.loc[UNW_SH_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0); - c->dwarf.loc[UNW_SH_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0); - c->dwarf.loc[UNW_SH_PR] = DWARF_LOC (sc_addr + LINUX_SC_PR_OFF, 0); - c->dwarf.loc[UNW_SH_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); - - /* Set SP/CFA and PC/IP. */ - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SH_R15], &c->dwarf.cfa); - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SH_PC], &c->dwarf.ip); - - c->dwarf.pi_valid = 0; - - return 1; -} - -PROTECTED int -unw_step (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - Debug (1, "(cursor=%p)\n", c); - - if (unw_is_signal_frame (cursor) > 0) - return unw_handle_signal_frame (cursor); - - ret = dwarf_step (&c->dwarf); - - if (unlikely (ret == -UNW_ESTOPUNWIND)) - return ret; - - if (unlikely (ret < 0)) - return 0; - - return (c->dwarf.ip == 0) ? 0 : 1; -} diff --git a/contrib/libunwind/src/sh/Lapply_reg_state.c b/contrib/libunwind/src/sh/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/sh/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/sh/Lcreate_addr_space.c b/contrib/libunwind/src/sh/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901..00000000000 --- a/contrib/libunwind/src/sh/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/contrib/libunwind/src/sh/Lget_proc_info.c b/contrib/libunwind/src/sh/Lget_proc_info.c deleted file mode 100644 index 69028b019fc..00000000000 --- a/contrib/libunwind/src/sh/Lget_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info.c" -#endif diff --git a/contrib/libunwind/src/sh/Lget_save_loc.c b/contrib/libunwind/src/sh/Lget_save_loc.c deleted file mode 100644 index 9ea048a9076..00000000000 --- a/contrib/libunwind/src/sh/Lget_save_loc.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_save_loc.c" -#endif diff --git a/contrib/libunwind/src/sh/Lglobal.c b/contrib/libunwind/src/sh/Lglobal.c deleted file mode 100644 index 6d7b489e14b..00000000000 --- a/contrib/libunwind/src/sh/Lglobal.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/contrib/libunwind/src/sh/Linit.c b/contrib/libunwind/src/sh/Linit.c deleted file mode 100644 index e9abfdd46a3..00000000000 --- a/contrib/libunwind/src/sh/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/contrib/libunwind/src/sh/Linit_local.c b/contrib/libunwind/src/sh/Linit_local.c deleted file mode 100644 index 68a1687e854..00000000000 --- a/contrib/libunwind/src/sh/Linit_local.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_local.c" -#endif diff --git a/contrib/libunwind/src/sh/Linit_remote.c b/contrib/libunwind/src/sh/Linit_remote.c deleted file mode 100644 index 58cb04ab7cd..00000000000 --- a/contrib/libunwind/src/sh/Linit_remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_remote.c" -#endif diff --git a/contrib/libunwind/src/sh/Lis_signal_frame.c b/contrib/libunwind/src/sh/Lis_signal_frame.c deleted file mode 100644 index b9a7c4f51ad..00000000000 --- a/contrib/libunwind/src/sh/Lis_signal_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gis_signal_frame.c" -#endif diff --git a/contrib/libunwind/src/sh/Lreg_states_iterate.c b/contrib/libunwind/src/sh/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/sh/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/sh/Lregs.c b/contrib/libunwind/src/sh/Lregs.c deleted file mode 100644 index 2c9c75cd7d9..00000000000 --- a/contrib/libunwind/src/sh/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/contrib/libunwind/src/sh/Lresume.c b/contrib/libunwind/src/sh/Lresume.c deleted file mode 100644 index 41a8cf003de..00000000000 --- a/contrib/libunwind/src/sh/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/contrib/libunwind/src/sh/Lstep.c b/contrib/libunwind/src/sh/Lstep.c deleted file mode 100644 index c1ac3c7547f..00000000000 --- a/contrib/libunwind/src/sh/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/contrib/libunwind/src/sh/gen-offsets.c b/contrib/libunwind/src/sh/gen-offsets.c deleted file mode 100644 index 16695a64896..00000000000 --- a/contrib/libunwind/src/sh/gen-offsets.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include - -#define UC(N,X) \ - printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X)) - -#define SC(N,X) \ - printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X)) - -int -main (void) -{ - printf ( -"/* Linux-specific definitions: */\n\n" - -"/* Define various structure offsets to simplify cross-compilation. */\n\n" - -"/* Offsets for SH Linux \"ucontext_t\": */\n\n"); - - UC ("FLAGS", uc_flags); - UC ("LINK", uc_link); - UC ("STACK", uc_stack); - UC ("MCONTEXT", uc_mcontext); - UC ("SIGMASK", uc_sigmask); - - printf ("\n/* Offsets for SH Linux \"struct sigcontext\": */\n\n"); - - SC ("R0", sc_regs[0]); - SC ("R1", sc_regs[1]); - SC ("R2", sc_regs[2]); - SC ("R3", sc_regs[3]); - SC ("R4", sc_regs[4]); - SC ("R5", sc_regs[5]); - SC ("R6", sc_regs[6]); - SC ("R7", sc_regs[7]); - SC ("R8", sc_regs[8]); - SC ("R9", sc_regs[9]); - SC ("R10", sc_regs[10]); - SC ("R11", sc_regs[11]); - SC ("R12", sc_regs[12]); - SC ("R13", sc_regs[13]); - SC ("R14", sc_regs[14]); - SC ("R15", sc_regs[15]); - - SC ("PC", sc_pc); - SC ("PR", sc_pr); - - return 0; -} diff --git a/contrib/libunwind/src/sh/init.h b/contrib/libunwind/src/sh/init.h deleted file mode 100644 index 36713fe89b0..00000000000 --- a/contrib/libunwind/src/sh/init.h +++ /dev/null @@ -1,73 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static inline int -common_init (struct cursor *c, unsigned use_prev_instr) -{ - int ret; - - c->dwarf.loc[UNW_SH_R0] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R0); - c->dwarf.loc[UNW_SH_R1] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R1); - c->dwarf.loc[UNW_SH_R2] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R2); - c->dwarf.loc[UNW_SH_R3] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R3); - c->dwarf.loc[UNW_SH_R4] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R4); - c->dwarf.loc[UNW_SH_R5] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R5); - c->dwarf.loc[UNW_SH_R6] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R6); - c->dwarf.loc[UNW_SH_R7] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R7); - c->dwarf.loc[UNW_SH_R8] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R8); - c->dwarf.loc[UNW_SH_R9] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R9); - c->dwarf.loc[UNW_SH_R10] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R10); - c->dwarf.loc[UNW_SH_R11] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R11); - c->dwarf.loc[UNW_SH_R12] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R12); - c->dwarf.loc[UNW_SH_R13] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R13); - c->dwarf.loc[UNW_SH_R14] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R14); - c->dwarf.loc[UNW_SH_R15] = DWARF_REG_LOC (&c->dwarf, UNW_SH_R15); - c->dwarf.loc[UNW_SH_PC] = DWARF_REG_LOC (&c->dwarf, UNW_SH_PC); - c->dwarf.loc[UNW_SH_PR] = DWARF_REG_LOC (&c->dwarf, UNW_SH_PR); - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_SH_PC], &c->dwarf.ip); - if (ret < 0) - return ret; - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_TDEP_SP], &c->dwarf.cfa); - if (ret < 0) - return ret; - - c->sigcontext_format = SH_SCF_NONE; - c->sigcontext_addr = 0; - c->sigcontext_sp = 0; - c->sigcontext_pc = 0; - - c->dwarf.args_size = 0; - c->dwarf.stash_frames = 0; - c->dwarf.use_prev_instr = use_prev_instr; - c->dwarf.pi_valid = 0; - c->dwarf.pi_is_dynamic = 0; - c->dwarf.hint = 0; - c->dwarf.prev_rs = 0; - - return 0; -} diff --git a/contrib/libunwind/src/sh/is_fpreg.c b/contrib/libunwind/src/sh/is_fpreg.c deleted file mode 100644 index c351f81c485..00000000000 --- a/contrib/libunwind/src/sh/is_fpreg.c +++ /dev/null @@ -1,32 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_is_fpreg (int regnum) -{ - /* FIXME: Support FP. */ - return 0; -} diff --git a/contrib/libunwind/src/sh/offsets.h b/contrib/libunwind/src/sh/offsets.h deleted file mode 100644 index b02d8aee1e0..00000000000 --- a/contrib/libunwind/src/sh/offsets.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Linux-specific definitions: */ - -/* Define various structure offsets to simplify cross-compilation. */ - -/* Offsets for SH Linux "ucontext_t": */ - -#define LINUX_UC_FLAGS_OFF 0x0 -#define LINUX_UC_LINK_OFF 0x4 -#define LINUX_UC_STACK_OFF 0x8 -#define LINUX_UC_MCONTEXT_OFF 0x14 -#define LINUX_UC_SIGMASK_OFF 0xFC - -/* Offsets for SH Linux "struct sigcontext": */ - -#define LINUX_SC_R0_OFF 0x4 -#define LINUX_SC_R1_OFF 0x8 -#define LINUX_SC_R2_OFF 0xC -#define LINUX_SC_R3_OFF 0x10 -#define LINUX_SC_R4_OFF 0x14 -#define LINUX_SC_R5_OFF 0x18 -#define LINUX_SC_R6_OFF 0x1C -#define LINUX_SC_R7_OFF 0x20 -#define LINUX_SC_R8_OFF 0x24 -#define LINUX_SC_R9_OFF 0x28 -#define LINUX_SC_R10_OFF 0x2C -#define LINUX_SC_R11_OFF 0x30 -#define LINUX_SC_R12_OFF 0x34 -#define LINUX_SC_R13_OFF 0x38 -#define LINUX_SC_R14_OFF 0x3C -#define LINUX_SC_R15_OFF 0x40 -#define LINUX_SC_PC_OFF 0x44 -#define LINUX_SC_PR_OFF 0x48 diff --git a/contrib/libunwind/src/sh/regname.c b/contrib/libunwind/src/sh/regname.c deleted file mode 100644 index dcab2405365..00000000000 --- a/contrib/libunwind/src/sh/regname.c +++ /dev/null @@ -1,56 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static const char *const regname[] = - { - [UNW_SH_R0] = "r0", - [UNW_SH_R1] = "r1", - [UNW_SH_R2] = "r2", - [UNW_SH_R3] = "r3", - [UNW_SH_R4] = "r4", - [UNW_SH_R5] = "r5", - [UNW_SH_R6] = "r6", - [UNW_SH_R7] = "r7", - [UNW_SH_R8] = "r8", - [UNW_SH_R9] = "r9", - [UNW_SH_R10] = "r10", - [UNW_SH_R11] = "r11", - [UNW_SH_R12] = "r12", - [UNW_SH_R13] = "r13", - [UNW_SH_R14] = "r14", - [UNW_SH_R15] = "r15", - [UNW_SH_PC] = "pc", - [UNW_SH_PR] = "pr", - }; - -PROTECTED const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < (unw_regnum_t) ARRAY_SIZE (regname) && regname[reg] != NULL) - return regname[reg]; - else - return "???"; -} diff --git a/contrib/libunwind/src/sh/siglongjmp.S b/contrib/libunwind/src/sh/siglongjmp.S deleted file mode 100644 index 9ca53d124b9..00000000000 --- a/contrib/libunwind/src/sh/siglongjmp.S +++ /dev/null @@ -1,8 +0,0 @@ - /* Dummy implementation for now. */ - - .globl _UI_siglongjmp_cont - .globl _UI_longjmp_cont - -_UI_siglongjmp_cont: -_UI_longjmp_cont: - rts diff --git a/contrib/libunwind/src/sh/unwind_i.h b/contrib/libunwind/src/sh/unwind_i.h deleted file mode 100644 index 3066d84631e..00000000000 --- a/contrib/libunwind/src/sh/unwind_i.h +++ /dev/null @@ -1,40 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include - -#include "libunwind_i.h" - -#define sh_lock UNW_OBJ(lock) -#define sh_local_resume UNW_OBJ(local_resume) -#define sh_local_addr_space_init UNW_OBJ(local_addr_space_init) - -extern void sh_local_addr_space_init (void); -extern int sh_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, - void *arg); - -#endif /* unwind_i_h */ diff --git a/contrib/libunwind/src/tilegx/Gapply_reg_state.c b/contrib/libunwind/src/tilegx/Gapply_reg_state.c deleted file mode 100644 index eec93046f56..00000000000 --- a/contrib/libunwind/src/tilegx/Gapply_reg_state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); -} diff --git a/contrib/libunwind/src/tilegx/Gcreate_addr_space.c b/contrib/libunwind/src/tilegx/Gcreate_addr_space.c deleted file mode 100644 index a2821a3d313..00000000000 --- a/contrib/libunwind/src/tilegx/Gcreate_addr_space.c +++ /dev/null @@ -1,65 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as = malloc (sizeof (*as)); - - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - /* - * Tilegx supports only big or little-endian, not weird stuff like - * PDP_ENDIAN. - */ - if (byte_order != 0 - && byte_order != __LITTLE_ENDIAN - && byte_order != __BIG_ENDIAN) - return NULL; - - if (byte_order == 0) - /* use host default: */ - as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); - else - as->big_endian = (byte_order == __BIG_ENDIAN); - - as->abi = UNW_TILEGX_ABI_N64; - as->addr_size = 8; - - return as; -#endif -} diff --git a/contrib/libunwind/src/tilegx/Gget_proc_info.c b/contrib/libunwind/src/tilegx/Gget_proc_info.c deleted file mode 100644 index f82700dd3a3..00000000000 --- a/contrib/libunwind/src/tilegx/Gget_proc_info.c +++ /dev/null @@ -1,48 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - ret = dwarf_make_proc_info (&c->dwarf); - - if (ret < 0) - { - /* On Tilegx, some routines i.e. _start() etc has no dwarf info. - Just simply mark the end of the frames. */ - memset (pi, 0, sizeof (*pi)); - pi->start_ip = c->dwarf.ip; - pi->end_ip = c->dwarf.ip + 1; - return 0; - } - - *pi = c->dwarf.pi; - return 0; -} diff --git a/contrib/libunwind/src/tilegx/Gget_save_loc.c b/contrib/libunwind/src/tilegx/Gget_save_loc.c deleted file mode 100644 index ec474e1885d..00000000000 --- a/contrib/libunwind/src/tilegx/Gget_save_loc.c +++ /dev/null @@ -1,62 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) -{ - struct cursor *c = (struct cursor *) cursor; - dwarf_loc_t loc; - - loc = DWARF_NULL_LOC; /* default to "not saved" */ - - if (reg <= UNW_TILEGX_R55) - loc = c->dwarf.loc[reg - UNW_TILEGX_R0]; - else - printf("\nInvalid register!"); - - memset (sloc, 0, sizeof (*sloc)); - - if (DWARF_IS_NULL_LOC (loc)) - { - sloc->type = UNW_SLT_NONE; - return 0; - } - -#if !defined(UNW_LOCAL_ONLY) - if (DWARF_IS_REG_LOC (loc)) - { - sloc->type = UNW_SLT_REG; - sloc->u.regnum = DWARF_GET_LOC (loc); - } - else -#endif - { - sloc->type = UNW_SLT_MEMORY; - sloc->u.addr = DWARF_GET_LOC (loc); - } - return 0; -} diff --git a/contrib/libunwind/src/tilegx/Gglobal.c b/contrib/libunwind/src/tilegx/Gglobal.c deleted file mode 100644 index e18f50a50f3..00000000000 --- a/contrib/libunwind/src/tilegx/Gglobal.c +++ /dev/null @@ -1,64 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "dwarf_i.h" - -__attribute__((weak)) -pthread_mutex_t tilegx_lock = PTHREAD_MUTEX_INITIALIZER; -HIDDEN int tdep_init_done; - -HIDDEN const uint8_t dwarf_to_unw_regnum_map[] = - { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55 - }; - -HIDDEN void -tdep_init (void) -{ - intrmask_t saved_mask; - - sigfillset (&unwi_full_mask); - - lock_acquire (&tilegx_lock, saved_mask); - - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - mi_init (); - dwarf_init (); - -#ifndef UNW_REMOTE_ONLY - tilegx_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - - out: - lock_release (&tilegx_lock, saved_mask); -} diff --git a/contrib/libunwind/src/tilegx/Ginit.c b/contrib/libunwind/src/tilegx/Ginit.c deleted file mode 100644 index a0bb69d7719..00000000000 --- a/contrib/libunwind/src/tilegx/Ginit.c +++ /dev/null @@ -1,167 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -PROTECTED unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; - -/* Return the address of the 64-bit slot in UC for REG (even for o32, - where registers are 32-bit, the slots are still 64-bit). */ - -static inline void * -uc_addr (ucontext_t *uc, int reg) -{ - if (reg >= UNW_TILEGX_R0 && reg < UNW_TILEGX_R0 + 56) - return &uc->uc_mcontext.gregs[reg - UNW_TILEGX_R0]; - else if (reg == UNW_TILEGX_PC) - return &uc->uc_mcontext.pc; - else - return NULL; -} - -# ifdef UNW_LOCAL_ONLY - -HIDDEN void * -tdep_uc_addr (ucontext_t *uc, int reg) -{ - char *addr = uc_addr (uc, reg); - return addr; -} - -# endif /* UNW_LOCAL_ONLY */ - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - -/* XXX fix me: there is currently no way to locate the dyn-info list - by a remote unwinder. On ia64, this is done via a special - unwind-table entry. Perhaps something similar can be done with - DWARF2 unwind info. */ - -static void -put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ - *dyn_info_list_addr = (unw_word_t) (intptr_t) &_U_dyn_info_list; - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - if ((long long)addr & (sizeof(unw_word_t) - 1)) - return 0; - - if (write) - { - Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val); - *(unw_word_t *) (intptr_t) addr = *val; - } - else - { - *val = *(unw_word_t *) (intptr_t) addr; - Debug (16, "mem[%llx] -> %llx\n", (long long) addr, (long long) *val); - } - return 0; -} - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, - void *arg) -{ - unw_word_t *addr; - ucontext_t *uc = arg; - - if (unw_is_fpreg (reg)) - goto badreg; - - Debug (16, "reg = %s\n", unw_regname (reg)); - if (!(addr = uc_addr (uc, reg))) - goto badreg; - - if (write) - { - *(unw_word_t *) (intptr_t) addr = (tilegx_reg_t) *val; - Debug (12, "%s <- %llx\n", unw_regname (reg), (long long) *val); - } - else - { - *val = (tilegx_reg_t) *(unw_word_t *) (intptr_t) addr; - Debug (12, "%s -> %llx\n", unw_regname (reg), (long long) *val); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - return elf_w (get_proc_name) (as, getpid (), ip, buf, buf_len, offp); -} - -__attribute__((weak)) void -tilegx_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); - - local_addr_space.abi = UNW_TILEGX_ABI_N64; - local_addr_space.addr_size = sizeof (void *); - local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; - local_addr_space.acc.find_proc_info = dwarf_find_proc_info; - local_addr_space.acc.put_unwind_info = put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = NULL; - local_addr_space.acc.resume = tilegx_local_resume; - local_addr_space.acc.get_proc_name = get_static_proc_name; - unw_flush_cache (&local_addr_space, 0, 0); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/tilegx/Ginit_local.c b/contrib/libunwind/src/tilegx/Ginit_local.c deleted file mode 100644 index 6aa679f05df..00000000000 --- a/contrib/libunwind/src/tilegx/Ginit_local.c +++ /dev/null @@ -1,80 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "init.h" - -#ifdef UNW_REMOTE_ONLY - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - return -UNW_EINVAL; -} - -#else /* !UNW_REMOTE_ONLY */ - -static int -unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) -{ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - memset(c, 0, sizeof(unw_cursor_t)); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = unw_local_addr_space; - - c->dwarf.as_arg = uc; - return common_init (c, use_prev_instr); -} - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - return unw_init_local_common(cursor, uc, 1); -} - -PROTECTED int -unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) -{ - if (!flag) - { - return unw_init_local_common(cursor, uc, 1); - } - else if (flag == UNW_INIT_SIGNAL_FRAME) - { - return unw_init_local_common(cursor, uc, 0); - } - else - { - return -UNW_EINVAL; - } -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/tilegx/Ginit_remote.c b/contrib/libunwind/src/tilegx/Ginit_remote.c deleted file mode 100644 index c55410085d8..00000000000 --- a/contrib/libunwind/src/tilegx/Ginit_remote.c +++ /dev/null @@ -1,47 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "init.h" -#include "unwind_i.h" - -PROTECTED int -unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) -{ -#ifdef UNW_LOCAL_ONLY - return -UNW_EINVAL; -#else /* !UNW_LOCAL_ONLY */ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = as; - c->dwarf.as_arg = as_arg; - - return common_init (c, 0); -#endif /* !UNW_LOCAL_ONLY */ -} diff --git a/contrib/libunwind/src/tilegx/Gis_signal_frame.c b/contrib/libunwind/src/tilegx/Gis_signal_frame.c deleted file mode 100644 index 96bd34adde3..00000000000 --- a/contrib/libunwind/src/tilegx/Gis_signal_frame.c +++ /dev/null @@ -1,115 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include -#include "offsets.h" - -#ifdef __linux__ -#include -#include -#else -# error "Only support Linux!" -#endif - -#define MOVELI_R10_RT_SIGRETURN \ - ( 0x000007e051483000ULL | \ - ((unsigned long)__NR_rt_sigreturn << 43) | \ - ((unsigned long)TREG_SYSCALL_NR << 31) ) -#define SWINT1 0x286b180051485000ULL - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor*) cursor; - unw_word_t w0, w1, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - ip = c->dwarf.ip; - - if (!ip || !a->access_mem || (ip & (sizeof(unw_word_t) - 1))) - return 0; - - if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0) - return ret; - - if ((ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0) - return ret; - - /* Return 1 if the IP points to a RT sigreturn sequence. */ - if (w0 == MOVELI_R10_RT_SIGRETURN && - w1 == SWINT1) - { - return 1; - } - return 0; -} - - -PROTECTED int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ - int i; - struct cursor *c = (struct cursor *) cursor; - unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; - struct dwarf_loc sp_loc = DWARF_LOC (sp_addr, 0); - int ret; - - if ((ret = dwarf_get (&c->dwarf, sp_loc, &sp)) < 0) - return -UNW_EUNSPEC; - - /* Save the SP and PC to be able to return execution at this point - later in time (unw_resume). */ - c->sigcontext_sp = c->dwarf.cfa; - c->sigcontext_pc = c->dwarf.ip; - - c->sigcontext_addr = sp_addr + sizeof (siginfo_t) + - C_ABI_SAVE_AREA_SIZE; - sc_addr = c->sigcontext_addr + LINUX_UC_MCONTEXT_OFF; - - /* Update the dwarf cursor. - Set the location of the registers to the corresponding addresses of the - uc_mcontext / sigcontext structure contents. */ - -#define SC_REG_OFFSET(X) (8 * X) - - for (i = UNW_TILEGX_R0; i <= UNW_TILEGX_R55; i++) - { - c->dwarf.loc[i] = DWARF_LOC (sc_addr + SC_REG_OFFSET(i), 0); - } - - /* Set SP/CFA and PC/IP. */ - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_TILEGX_R54], &c->dwarf.cfa); - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_TILEGX_R55], &c->dwarf.ip); - - return 1; -} diff --git a/contrib/libunwind/src/tilegx/Greg_states_iterate.c b/contrib/libunwind/src/tilegx/Greg_states_iterate.c deleted file mode 100644 index a39837a1781..00000000000 --- a/contrib/libunwind/src/tilegx/Greg_states_iterate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_reg_states_iterate (&c->dwarf, cb, token); -} diff --git a/contrib/libunwind/src/tilegx/Gregs.c b/contrib/libunwind/src/tilegx/Gregs.c deleted file mode 100644 index 565c6f4432a..00000000000 --- a/contrib/libunwind/src/tilegx/Gregs.c +++ /dev/null @@ -1,76 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - dwarf_loc_t loc = DWARF_NULL_LOC; - - if (reg == UNW_TILEGX_R54 && !write) - { - reg = UNW_TILEGX_CFA; - } - - if (reg <= UNW_TILEGX_R55) - loc = c->dwarf.loc[reg - UNW_TILEGX_R0]; - else if (reg == UNW_TILEGX_CFA) - { - if (write) - return -UNW_EREADONLYREG; - *valp = c->dwarf.cfa; - return 0; - } - else - { - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; - } - - if (write) - { - if (ci->dwarf.use_prev_instr == 0) { - if (reg == UNW_TILEGX_PC) - c->dwarf.ip = *valp; /* update the IP cache */ - } - else { - if (reg == UNW_TILEGX_R55) - c->dwarf.ip = *valp; /* update the IP cache */ - } - return dwarf_put (&c->dwarf, loc, *valp); - } - else - return dwarf_get (&c->dwarf, loc, valp); -} - -HIDDEN int -tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, - int write) -{ - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} diff --git a/contrib/libunwind/src/tilegx/Gresume.c b/contrib/libunwind/src/tilegx/Gresume.c deleted file mode 100644 index f532fd852a3..00000000000 --- a/contrib/libunwind/src/tilegx/Gresume.c +++ /dev/null @@ -1,94 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - - -#include "unwind_i.h" -#include "offsets.h" -#include - -#ifndef UNW_REMOTE_ONLY - -HIDDEN inline int -tilegx_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ - int i; - struct cursor *c = (struct cursor *) cursor; - ucontext_t *uc = c->dwarf.as_arg; - - Debug (1, "(cursor=%p\n", c); - - return setcontext(uc); -} - -#endif /* !UNW_REMOTE_ONLY */ - -static inline void -establish_machine_state (struct cursor *c) -{ - unw_addr_space_t as = c->dwarf.as; - void *arg = c->dwarf.as_arg; - unw_fpreg_t fpval; - unw_word_t val; - int reg; - - Debug (8, "copying out cursor state\n"); - - for (reg = 0; reg <= UNW_REG_LAST; ++reg) - { - Debug (16, "copying %s %d\n", unw_regname (reg), reg); - - if (unw_is_fpreg (reg)) - { - Debug (1, "no fp!"); - abort (); - } - else - { - if (tdep_access_reg (c, reg, &val, 0) >= 0) - as->acc.access_reg (as, reg, &val, 1, arg); - } - } -} - -PROTECTED int -unw_resume (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - - Debug (1, "(cursor=%p) ip=0x%lx\n", c, c->dwarf.ip); - - if (!c->dwarf.ip) - { - /* This can happen easily when the frame-chain gets truncated - due to bad or missing unwind-info. */ - Debug (1, "refusing to resume execution at address 0\n"); - return -UNW_EINVAL; - } - - establish_machine_state (c); - - return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, - c->dwarf.as_arg); -} diff --git a/contrib/libunwind/src/tilegx/Gstep.c b/contrib/libunwind/src/tilegx/Gstep.c deleted file mode 100644 index 1d32f960632..00000000000 --- a/contrib/libunwind/src/tilegx/Gstep.c +++ /dev/null @@ -1,53 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" - -PROTECTED int -unw_step (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - Debug (1, "(cursor=%p, ip=0x%016lx, sp=0x%016lx)\n", - c, c->dwarf.ip, c->dwarf.cfa); - - /* Special handling the singal frame. */ - if (unw_is_signal_frame (cursor) > 0) - return unw_handle_signal_frame (cursor); - - /* Try DWARF-based unwinding... */ - ret = dwarf_step (&c->dwarf); - - if (unlikely (ret == -UNW_ESTOPUNWIND)) - return ret; - - /* Dwarf unwinding didn't work, stop. */ - if (unlikely (ret < 0)) - return 0; - - return (c->dwarf.ip == 0) ? 0 : 1; -} diff --git a/contrib/libunwind/src/tilegx/Lapply_reg_state.c b/contrib/libunwind/src/tilegx/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/tilegx/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Lcreate_addr_space.c b/contrib/libunwind/src/tilegx/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901..00000000000 --- a/contrib/libunwind/src/tilegx/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Lget_proc_info.c b/contrib/libunwind/src/tilegx/Lget_proc_info.c deleted file mode 100644 index 69028b019fc..00000000000 --- a/contrib/libunwind/src/tilegx/Lget_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Lget_save_loc.c b/contrib/libunwind/src/tilegx/Lget_save_loc.c deleted file mode 100644 index 9ea048a9076..00000000000 --- a/contrib/libunwind/src/tilegx/Lget_save_loc.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_save_loc.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Lglobal.c b/contrib/libunwind/src/tilegx/Lglobal.c deleted file mode 100644 index 6d7b489e14b..00000000000 --- a/contrib/libunwind/src/tilegx/Lglobal.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Linit.c b/contrib/libunwind/src/tilegx/Linit.c deleted file mode 100644 index e9abfdd46a3..00000000000 --- a/contrib/libunwind/src/tilegx/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Linit_local.c b/contrib/libunwind/src/tilegx/Linit_local.c deleted file mode 100644 index 68a1687e854..00000000000 --- a/contrib/libunwind/src/tilegx/Linit_local.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_local.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Linit_remote.c b/contrib/libunwind/src/tilegx/Linit_remote.c deleted file mode 100644 index 58cb04ab7cd..00000000000 --- a/contrib/libunwind/src/tilegx/Linit_remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_remote.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Lis_signal_frame.c b/contrib/libunwind/src/tilegx/Lis_signal_frame.c deleted file mode 100644 index b9a7c4f51ad..00000000000 --- a/contrib/libunwind/src/tilegx/Lis_signal_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gis_signal_frame.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Lreg_states_iterate.c b/contrib/libunwind/src/tilegx/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/tilegx/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Lregs.c b/contrib/libunwind/src/tilegx/Lregs.c deleted file mode 100644 index 2c9c75cd7d9..00000000000 --- a/contrib/libunwind/src/tilegx/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Lresume.c b/contrib/libunwind/src/tilegx/Lresume.c deleted file mode 100644 index 41a8cf003de..00000000000 --- a/contrib/libunwind/src/tilegx/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/contrib/libunwind/src/tilegx/Lstep.c b/contrib/libunwind/src/tilegx/Lstep.c deleted file mode 100644 index c1ac3c7547f..00000000000 --- a/contrib/libunwind/src/tilegx/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/contrib/libunwind/src/tilegx/elfxx.c b/contrib/libunwind/src/tilegx/elfxx.c deleted file mode 100644 index 07d3d12b94f..00000000000 --- a/contrib/libunwind/src/tilegx/elfxx.c +++ /dev/null @@ -1,27 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -#include "../src/elfxx.c" diff --git a/contrib/libunwind/src/tilegx/gen-offsets.c b/contrib/libunwind/src/tilegx/gen-offsets.c deleted file mode 100644 index 8704bb215e3..00000000000 --- a/contrib/libunwind/src/tilegx/gen-offsets.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include - -#define UC(N,X) \ - printf ("#define LINUX_UC_" N "_OFF\t0x%X\n", offsetof (ucontext_t, X)) - -#define SC(N,X) \ - printf ("#define LINUX_SC_" N "_OFF\t0x%X\n", offsetof (struct sigcontext, X)) - -int -main (void) -{ - printf ( -"/* Linux-specific definitions: */\n\n" - -"/* Define various structure offsets to simplify cross-compilation. */\n\n" - -"/* Offsets for TILEGX Linux \"ucontext_t\": */\n\n"); - - UC ("FLAGS", uc_flags); - UC ("LINK", uc_link); - UC ("STACK", uc_stack); - UC ("MCONTEXT", uc_mcontext); - UC ("SIGMASK", uc_sigmask); - - UC ("MCONTEXT_GREGS", uc_mcontext.gregs); - - return 0; -} diff --git a/contrib/libunwind/src/tilegx/getcontext.S b/contrib/libunwind/src/tilegx/getcontext.S deleted file mode 100644 index fbc8654bc7f..00000000000 --- a/contrib/libunwind/src/tilegx/getcontext.S +++ /dev/null @@ -1,36 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "offsets.h" -#include - - .text - # define REG(X) LINUX_UC_MCONTEXT_GREGS + 8 * (X) - .global _Utilegx_getcontext - .type _Utilegx_getcontext, %function - # This is a stub version of getcontext() for TILEGX. -_Utilegx_getcontext: - - diff --git a/contrib/libunwind/src/tilegx/init.h b/contrib/libunwind/src/tilegx/init.h deleted file mode 100644 index 0e0f7fd1da8..00000000000 --- a/contrib/libunwind/src/tilegx/init.h +++ /dev/null @@ -1,63 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static inline int -common_init (struct cursor *c, unsigned use_prev_instr) -{ - int ret, i; - - for (i = 0; i < 56; i++) - c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_R0 + i); - for (i = 56; i < DWARF_NUM_PRESERVED_REGS; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - - if (use_prev_instr == 0) - ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_PC), - &c->dwarf.ip); - else - ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_R55), - &c->dwarf.ip); - - if (ret < 0) - return ret; - - ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_TILEGX_R54), - &c->dwarf.cfa); - - if (ret < 0) - return ret; - - c->dwarf.args_size = 0; - c->dwarf.stash_frames = 0; - c->dwarf.use_prev_instr = use_prev_instr; - c->dwarf.pi_valid = 0; - c->dwarf.pi_is_dynamic = 0; - c->dwarf.hint = 0; - c->dwarf.prev_rs = 0; - - return 0; -} diff --git a/contrib/libunwind/src/tilegx/is_fpreg.c b/contrib/libunwind/src/tilegx/is_fpreg.c deleted file mode 100644 index 118e055ef24..00000000000 --- a/contrib/libunwind/src/tilegx/is_fpreg.c +++ /dev/null @@ -1,33 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -/* TILEGX has no FP. */ - -PROTECTED int -unw_is_fpreg (int regnum) -{ - return 0; -} diff --git a/contrib/libunwind/src/tilegx/offsets.h b/contrib/libunwind/src/tilegx/offsets.h deleted file mode 100644 index 6d30f1edcff..00000000000 --- a/contrib/libunwind/src/tilegx/offsets.h +++ /dev/null @@ -1,12 +0,0 @@ -/* Linux-specific definitions: */ - -/* Define various structure offsets to simplify cross-compilation. */ - -/* Offsets for TILEGX Linux "ucontext_t": */ - -#define LINUX_UC_FLAGS_OFF 0x0 -#define LINUX_UC_LINK_OFF 0x8 -#define LINUX_UC_STACK_OFF 0x10 -#define LINUX_UC_MCONTEXT_OFF 0x28 -#define LINUX_UC_SIGMASK_OFF 0x228 -#define LINUX_UC_MCONTEXT_GREGS 0x28 diff --git a/contrib/libunwind/src/tilegx/regname.c b/contrib/libunwind/src/tilegx/regname.c deleted file mode 100644 index fd73804661f..00000000000 --- a/contrib/libunwind/src/tilegx/regname.c +++ /dev/null @@ -1,55 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2014 Tilera Corp. - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static const char *regname[] = - { - /* 0. */ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - /* 8. */ - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - /* 16. */ - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - /* 24. */ - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", - /* 32. */ - "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", - /* 40. */ - "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", - /* 48. */ - "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", - /* pc, cfa */ - "pc", "cfa" - }; - -PROTECTED const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) - return regname[reg]; - else - return "???"; -} diff --git a/contrib/libunwind/src/tilegx/siglongjmp.S b/contrib/libunwind/src/tilegx/siglongjmp.S deleted file mode 100644 index bccb1c77854..00000000000 --- a/contrib/libunwind/src/tilegx/siglongjmp.S +++ /dev/null @@ -1,7 +0,0 @@ - /* Dummy implementation for now. */ - .globl _UI_siglongjmp_cont - .globl _UI_longjmp_cont - -_UI_siglongjmp_cont: -_UI_longjmp_cont: - jrp lr diff --git a/contrib/libunwind/src/tilegx/unwind_i.h b/contrib/libunwind/src/tilegx/unwind_i.h deleted file mode 100644 index aac7be38882..00000000000 --- a/contrib/libunwind/src/tilegx/unwind_i.h +++ /dev/null @@ -1,44 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include -#include - -#include - -#include "libunwind_i.h" - -#define tilegx_local_resume UNW_OBJ(local_resume) -#define tilegx_local_addr_space_init UNW_OBJ(local_addr_space_init) - -extern int tilegx_local_resume (unw_addr_space_t as, - unw_cursor_t *cursor, - void *arg); - -extern void tilegx_local_addr_space_init (void); - -#endif /* unwind_i_h */ diff --git a/contrib/libunwind/src/unwind/Backtrace.c b/contrib/libunwind/src/unwind/Backtrace.c deleted file mode 100644 index 50f1fb613a3..00000000000 --- a/contrib/libunwind/src/unwind/Backtrace.c +++ /dev/null @@ -1,56 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED _Unwind_Reason_Code -_Unwind_Backtrace (_Unwind_Trace_Fn trace, void *trace_parameter) -{ - struct _Unwind_Context context; - unw_context_t uc; - int ret; - - if (_Unwind_InitContext (&context, &uc) < 0) - return _URC_FATAL_PHASE1_ERROR; - - /* Phase 1 (search phase) */ - - while (1) - { - if ((ret = unw_step (&context.cursor)) <= 0) - { - if (ret == 0) - return _URC_END_OF_STACK; - else - return _URC_FATAL_PHASE1_ERROR; - } - - if ((*trace) (&context, trace_parameter) != _URC_NO_REASON) - return _URC_FATAL_PHASE1_ERROR; - } -} - -_Unwind_Reason_Code __libunwind_Unwind_Backtrace (_Unwind_Trace_Fn, void *) - ALIAS (_Unwind_Backtrace); diff --git a/contrib/libunwind/src/unwind/DeleteException.c b/contrib/libunwind/src/unwind/DeleteException.c deleted file mode 100644 index 79be65e4565..00000000000 --- a/contrib/libunwind/src/unwind/DeleteException.c +++ /dev/null @@ -1,38 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED void -_Unwind_DeleteException (struct _Unwind_Exception *exception_object) -{ - _Unwind_Exception_Cleanup_Fn cleanup = exception_object->exception_cleanup; - - if (cleanup) - (*cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object); -} - -void __libunwind_Unwind_DeleteException (struct _Unwind_Exception *) - ALIAS (_Unwind_DeleteException); diff --git a/contrib/libunwind/src/unwind/FindEnclosingFunction.c b/contrib/libunwind/src/unwind/FindEnclosingFunction.c deleted file mode 100644 index b9873da5f6d..00000000000 --- a/contrib/libunwind/src/unwind/FindEnclosingFunction.c +++ /dev/null @@ -1,42 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED void * -_Unwind_FindEnclosingFunction (void *ip) -{ - unw_proc_info_t pi; - - if (unw_get_proc_info_by_ip (unw_local_addr_space, - (unw_word_t) (uintptr_t) ip, &pi, 0) - < 0) - return NULL; - - return (void *) (uintptr_t) pi.start_ip; -} - -void *__libunwind_Unwind_FindEnclosingFunction (void *) - ALIAS (_Unwind_FindEnclosingFunction); diff --git a/contrib/libunwind/src/unwind/ForcedUnwind.c b/contrib/libunwind/src/unwind/ForcedUnwind.c deleted file mode 100644 index da8a60e2262..00000000000 --- a/contrib/libunwind/src/unwind/ForcedUnwind.c +++ /dev/null @@ -1,52 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED _Unwind_Reason_Code -_Unwind_ForcedUnwind (struct _Unwind_Exception *exception_object, - _Unwind_Stop_Fn stop, void *stop_parameter) -{ - struct _Unwind_Context context; - unw_context_t uc; - - /* We check "stop" here to tell the compiler's inliner that - exception_object->private_1 isn't NULL when calling - _Unwind_Phase2(). */ - if (!stop) - return _URC_FATAL_PHASE2_ERROR; - - if (_Unwind_InitContext (&context, &uc) < 0) - return _URC_FATAL_PHASE2_ERROR; - - exception_object->private_1 = (unsigned long) stop; - exception_object->private_2 = (unsigned long) stop_parameter; - - return _Unwind_Phase2 (exception_object, &context); -} - -_Unwind_Reason_Code __libunwind_Unwind_ForcedUnwind (struct _Unwind_Exception*, - _Unwind_Stop_Fn, void *) - ALIAS (_Unwind_ForcedUnwind); diff --git a/contrib/libunwind/src/unwind/GetBSP.c b/contrib/libunwind/src/unwind/GetBSP.c deleted file mode 100644 index 253fde05f40..00000000000 --- a/contrib/libunwind/src/unwind/GetBSP.c +++ /dev/null @@ -1,42 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED unsigned long -_Unwind_GetBSP (struct _Unwind_Context *context) -{ -#ifdef UNW_TARGET_IA64 - unw_word_t val; - - unw_get_reg (&context->cursor, UNW_IA64_BSP, &val); - return val; -#else - return 0; -#endif -} - -unsigned long __libunwind_Unwind_GetBSP (struct _Unwind_Context *) - ALIAS (_Unwind_GetBSP); diff --git a/contrib/libunwind/src/unwind/GetCFA.c b/contrib/libunwind/src/unwind/GetCFA.c deleted file mode 100644 index 7975b1d3e6d..00000000000 --- a/contrib/libunwind/src/unwind/GetCFA.c +++ /dev/null @@ -1,38 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED unsigned long -_Unwind_GetCFA (struct _Unwind_Context *context) -{ - unw_word_t val; - - unw_get_reg (&context->cursor, UNW_REG_SP, &val); - return val; -} - -unsigned long __libunwind_Unwind_GetCFA (struct _Unwind_Context *) - ALIAS (_Unwind_GetCFA); diff --git a/contrib/libunwind/src/unwind/GetDataRelBase.c b/contrib/libunwind/src/unwind/GetDataRelBase.c deleted file mode 100644 index 9bdd4cb0c16..00000000000 --- a/contrib/libunwind/src/unwind/GetDataRelBase.c +++ /dev/null @@ -1,39 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED unsigned long -_Unwind_GetDataRelBase (struct _Unwind_Context *context) -{ - unw_proc_info_t pi; - - pi.gp = 0; - unw_get_proc_info (&context->cursor, &pi); - return pi.gp; -} - -unsigned long __libunwind_Unwind_GetDataRelBase (struct _Unwind_Context *) - ALIAS (_Unwind_GetDataRelBase); diff --git a/contrib/libunwind/src/unwind/GetGR.c b/contrib/libunwind/src/unwind/GetGR.c deleted file mode 100644 index b7ab05c4b66..00000000000 --- a/contrib/libunwind/src/unwind/GetGR.c +++ /dev/null @@ -1,43 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED unsigned long -_Unwind_GetGR (struct _Unwind_Context *context, int index) -{ - unw_word_t val; - - if (index == UNW_REG_SP && context->end_of_stack) - /* _Unwind_ForcedUnwind() requires us to return a NULL - stack-pointer after reaching the end of the stack. */ - return 0; - - unw_get_reg (&context->cursor, index, &val); - return val; -} - -unsigned long __libunwind_Unwind_GetGR (struct _Unwind_Context *, int) - ALIAS (_Unwind_GetGR); diff --git a/contrib/libunwind/src/unwind/GetIP.c b/contrib/libunwind/src/unwind/GetIP.c deleted file mode 100644 index e93853d0802..00000000000 --- a/contrib/libunwind/src/unwind/GetIP.c +++ /dev/null @@ -1,38 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED unsigned long -_Unwind_GetIP (struct _Unwind_Context *context) -{ - unw_word_t val; - - unw_get_reg (&context->cursor, UNW_REG_IP, &val); - return val; -} - -unsigned long __libunwind_Unwind_GetIP (struct _Unwind_Context *) - ALIAS (_Unwind_GetIP); diff --git a/contrib/libunwind/src/unwind/GetIPInfo.c b/contrib/libunwind/src/unwind/GetIPInfo.c deleted file mode 100644 index 9105396a28f..00000000000 --- a/contrib/libunwind/src/unwind/GetIPInfo.c +++ /dev/null @@ -1,42 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2009 Red Hat - Contributed by Jan Kratochvil - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -/* gcc/unwind-dw2.c: Retrieve the return address and flag whether that IP is - before or after first not yet fully executed instruction. */ - -PROTECTED unsigned long -_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn) -{ - unw_word_t val; - - unw_get_reg (&context->cursor, UNW_REG_IP, &val); - *ip_before_insn = unw_is_signal_frame (&context->cursor); - return val; -} - -unsigned long __libunwind_Unwind_GetIPInfo (struct _Unwind_Context *, int *) - ALIAS (_Unwind_GetIPInfo); diff --git a/contrib/libunwind/src/unwind/GetLanguageSpecificData.c b/contrib/libunwind/src/unwind/GetLanguageSpecificData.c deleted file mode 100644 index df52c929034..00000000000 --- a/contrib/libunwind/src/unwind/GetLanguageSpecificData.c +++ /dev/null @@ -1,40 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED unsigned long -_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context) -{ - unw_proc_info_t pi; - - pi.lsda = 0; - unw_get_proc_info (&context->cursor, &pi); - return pi.lsda; -} - -unsigned long -__libunwind_Unwind_GetLanguageSpecificData (struct _Unwind_Context *) - ALIAS (_Unwind_GetLanguageSpecificData); diff --git a/contrib/libunwind/src/unwind/GetRegionStart.c b/contrib/libunwind/src/unwind/GetRegionStart.c deleted file mode 100644 index f0da344985e..00000000000 --- a/contrib/libunwind/src/unwind/GetRegionStart.c +++ /dev/null @@ -1,39 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED unsigned long -_Unwind_GetRegionStart (struct _Unwind_Context *context) -{ - unw_proc_info_t pi; - - pi.start_ip = 0; - unw_get_proc_info (&context->cursor, &pi); - return pi.start_ip; -} - -unsigned long __libunwind_Unwind_GetRegionStart (struct _Unwind_Context *) - ALIAS (_Unwind_GetRegionStart); diff --git a/contrib/libunwind/src/unwind/GetTextRelBase.c b/contrib/libunwind/src/unwind/GetTextRelBase.c deleted file mode 100644 index d0826e7f2a4..00000000000 --- a/contrib/libunwind/src/unwind/GetTextRelBase.c +++ /dev/null @@ -1,35 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED unsigned long -_Unwind_GetTextRelBase (struct _Unwind_Context *context) -{ - return 0; -} - -unsigned long __libunwind_Unwind_GetTextRelBase (struct _Unwind_Context *) - ALIAS (_Unwind_GetTextRelBase); diff --git a/contrib/libunwind/src/unwind/RaiseException.c b/contrib/libunwind/src/unwind/RaiseException.c deleted file mode 100644 index cdf134a942f..00000000000 --- a/contrib/libunwind/src/unwind/RaiseException.c +++ /dev/null @@ -1,103 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED _Unwind_Reason_Code -_Unwind_RaiseException (struct _Unwind_Exception *exception_object) -{ - uint64_t exception_class = exception_object->exception_class; - _Unwind_Personality_Fn personality; - struct _Unwind_Context context; - _Unwind_Reason_Code reason; - unw_proc_info_t pi; - unw_context_t uc; - unw_word_t ip; - int ret; - - Debug (1, "(exception_object=%p)\n", exception_object); - - if (_Unwind_InitContext (&context, &uc) < 0) - return _URC_FATAL_PHASE1_ERROR; - - /* Phase 1 (search phase) */ - - while (1) - { - if ((ret = unw_step (&context.cursor)) <= 0) - { - if (ret == 0) - { - Debug (1, "no handler found\n"); - return _URC_END_OF_STACK; - } - else - return _URC_FATAL_PHASE1_ERROR; - } - - if (unw_get_proc_info (&context.cursor, &pi) < 0) - return _URC_FATAL_PHASE1_ERROR; - - personality = (_Unwind_Personality_Fn) (uintptr_t) pi.handler; - if (personality) - { - reason = (*personality) (_U_VERSION, _UA_SEARCH_PHASE, - exception_class, exception_object, - &context); - if (reason != _URC_CONTINUE_UNWIND) - { - if (reason == _URC_HANDLER_FOUND) - break; - else - { - Debug (1, "personality returned %d\n", reason); - return _URC_FATAL_PHASE1_ERROR; - } - } - } - } - - /* Exceptions are associated with IP-ranges. If a given exception - is handled at a particular IP, it will _always_ be handled at - that IP. If this weren't true, we'd have to track the tuple - (IP,SP,BSP) to uniquely identify the stack frame that's handling - the exception. */ - if (unw_get_reg (&context.cursor, UNW_REG_IP, &ip) < 0) - return _URC_FATAL_PHASE1_ERROR; - exception_object->private_1 = 0; /* clear "stop" pointer */ - exception_object->private_2 = ip; /* save frame marker */ - - Debug (1, "found handler for IP=%lx; entering cleanup phase\n", (long) ip); - - /* Reset the cursor to the first frame: */ - if (unw_init_local (&context.cursor, &uc) < 0) - return _URC_FATAL_PHASE1_ERROR; - - return _Unwind_Phase2 (exception_object, &context); -} - -_Unwind_Reason_Code -__libunwind_Unwind_RaiseException (struct _Unwind_Exception *) - ALIAS (_Unwind_RaiseException); diff --git a/contrib/libunwind/src/unwind/Resume.c b/contrib/libunwind/src/unwind/Resume.c deleted file mode 100644 index dd0a44bc86c..00000000000 --- a/contrib/libunwind/src/unwind/Resume.c +++ /dev/null @@ -1,42 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED void -_Unwind_Resume (struct _Unwind_Exception *exception_object) -{ - struct _Unwind_Context context; - unw_context_t uc; - - if (_Unwind_InitContext (&context, &uc) < 0) - abort (); - - _Unwind_Phase2 (exception_object, &context); - abort (); -} - -void __libunwind_Unwind_Resume (struct _Unwind_Exception *) - ALIAS (_Unwind_Resume); diff --git a/contrib/libunwind/src/unwind/Resume_or_Rethrow.c b/contrib/libunwind/src/unwind/Resume_or_Rethrow.c deleted file mode 100644 index d60e0383214..00000000000 --- a/contrib/libunwind/src/unwind/Resume_or_Rethrow.c +++ /dev/null @@ -1,47 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED _Unwind_Reason_Code -_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exception_object) -{ - struct _Unwind_Context context; - unw_context_t uc; - - if (exception_object->private_1) - { - if (_Unwind_InitContext (&context, &uc) < 0) - return _URC_FATAL_PHASE2_ERROR; - - return _Unwind_Phase2 (exception_object, &context); - } - else - return _Unwind_RaiseException (exception_object); -} - -_Unwind_Reason_Code -__libunwind_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *) - ALIAS (_Unwind_Resume_or_Rethrow); diff --git a/contrib/libunwind/src/unwind/SetGR.c b/contrib/libunwind/src/unwind/SetGR.c deleted file mode 100644 index 143b354925d..00000000000 --- a/contrib/libunwind/src/unwind/SetGR.c +++ /dev/null @@ -1,47 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" -#ifdef UNW_TARGET_X86 -#include "dwarf_i.h" -#endif - -PROTECTED void -_Unwind_SetGR (struct _Unwind_Context *context, int index, - unsigned long new_value) -{ -#ifdef UNW_TARGET_X86 - index = dwarf_to_unw_regnum(index); -#endif - unw_set_reg (&context->cursor, index, new_value); -#ifdef UNW_TARGET_IA64 - if (index >= UNW_IA64_GR && index <= UNW_IA64_GR + 127) - /* Clear the NaT bit. */ - unw_set_reg (&context->cursor, UNW_IA64_NAT + (index - UNW_IA64_GR), 0); -#endif -} - -void __libunwind_Unwind_SetGR (struct _Unwind_Context *, int, unsigned long) - ALIAS (_Unwind_SetGR); diff --git a/contrib/libunwind/src/unwind/SetIP.c b/contrib/libunwind/src/unwind/SetIP.c deleted file mode 100644 index c55ab9718eb..00000000000 --- a/contrib/libunwind/src/unwind/SetIP.c +++ /dev/null @@ -1,35 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind-internal.h" - -PROTECTED void -_Unwind_SetIP (struct _Unwind_Context *context, unsigned long new_value) -{ - unw_set_reg (&context->cursor, UNW_REG_IP, new_value); -} - -void __libunwind_Unwind_SetIP (struct _Unwind_Context *, unsigned long) - ALIAS (_Unwind_SetIP); diff --git a/contrib/libunwind/src/unwind/libunwind.pc.in b/contrib/libunwind/src/unwind/libunwind.pc.in deleted file mode 100644 index 1505c5d6f67..00000000000 --- a/contrib/libunwind/src/unwind/libunwind.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libunwind -Description: libunwind base library -Version: @VERSION@ -Libs: -L${libdir} -lunwind -Libs.private: @LIBLZMA@ -Cflags: -I${includedir} diff --git a/contrib/libunwind/src/unwind/unwind-internal.h b/contrib/libunwind/src/unwind/unwind-internal.h deleted file mode 100644 index c68fc3c5ed3..00000000000 --- a/contrib/libunwind/src/unwind/unwind-internal.h +++ /dev/null @@ -1,140 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_internal_h -#define unwind_internal_h - -#define UNW_LOCAL_ONLY - -#include -#include -#include - -#include "libunwind_i.h" - -/* The version of the _Unwind_*() interface implemented by this code. */ -#define _U_VERSION 1 - -typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn) - (int, _Unwind_Action, uint64_t, struct _Unwind_Exception *, - struct _Unwind_Context *); - -struct _Unwind_Context { - unw_cursor_t cursor; - int end_of_stack; /* set to 1 if the end of stack was reached */ -}; - -/* This must be a macro because unw_getcontext() must be invoked from - the callee, even if optimization (and hence inlining) is turned - off. The macro arguments MUST NOT have any side-effects. */ -#define _Unwind_InitContext(context, uc) \ - ((context)->end_of_stack = 0, \ - ((unw_getcontext (uc) < 0 || unw_init_local (&(context)->cursor, uc) < 0) \ - ? -1 : 0)) - -static _Unwind_Reason_Code ALWAYS_INLINE -_Unwind_Phase2 (struct _Unwind_Exception *exception_object, - struct _Unwind_Context *context) -{ - _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) exception_object->private_1; - uint64_t exception_class = exception_object->exception_class; - void *stop_parameter = (void *) exception_object->private_2; - _Unwind_Personality_Fn personality; - _Unwind_Reason_Code reason; - _Unwind_Action actions; - unw_proc_info_t pi; - unw_word_t ip; - int ret; - - actions = _UA_CLEANUP_PHASE; - if (stop) - actions |= _UA_FORCE_UNWIND; - - while (1) - { - ret = unw_step (&context->cursor); - if (ret <= 0) - { - if (ret == 0) - { - actions |= _UA_END_OF_STACK; - context->end_of_stack = 1; - } - else - return _URC_FATAL_PHASE2_ERROR; - } - - if (stop) - { - reason = (*stop) (_U_VERSION, actions, exception_class, - exception_object, context, stop_parameter); - if (reason != _URC_NO_REASON) - /* Stop function may return _URC_FATAL_PHASE2_ERROR if - it's unable to handle end-of-stack condition or - _URC_FATAL_PHASE2_ERROR if something is wrong. Not - that it matters: the resulting state is indeterminate - anyhow so we must return _URC_FATAL_PHASE2_ERROR... */ - return _URC_FATAL_PHASE2_ERROR; - } - - if (context->end_of_stack - || unw_get_proc_info (&context->cursor, &pi) < 0) - return _URC_FATAL_PHASE2_ERROR; - - personality = (_Unwind_Personality_Fn) (uintptr_t) pi.handler; - if (personality) - { - if (!stop) - { - if (unw_get_reg (&context->cursor, UNW_REG_IP, &ip) < 0) - return _URC_FATAL_PHASE2_ERROR; - - if ((unsigned long) stop_parameter == ip) - actions |= _UA_HANDLER_FRAME; - } - - reason = (*personality) (_U_VERSION, actions, exception_class, - exception_object, context); - if (reason != _URC_CONTINUE_UNWIND) - { - if (reason == _URC_INSTALL_CONTEXT) - { - /* we may regain control via _Unwind_Resume() */ - unw_resume (&context->cursor); - abort (); - } - else - return _URC_FATAL_PHASE2_ERROR; - } - if (actions & _UA_HANDLER_FRAME) - /* The personality routine for the handler-frame changed - it's mind; that's a no-no... */ - abort (); - } - } - return _URC_FATAL_PHASE2_ERROR; /* shouldn't be reached */ -} - -#endif /* unwind_internal_h */ diff --git a/contrib/libunwind/src/x86/Gapply_reg_state.c b/contrib/libunwind/src/x86/Gapply_reg_state.c deleted file mode 100644 index eec93046f56..00000000000 --- a/contrib/libunwind/src/x86/Gapply_reg_state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); -} diff --git a/contrib/libunwind/src/x86/Gcreate_addr_space.c b/contrib/libunwind/src/x86/Gcreate_addr_space.c deleted file mode 100644 index 45fec6da8d0..00000000000 --- a/contrib/libunwind/src/x86/Gcreate_addr_space.c +++ /dev/null @@ -1,58 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -#if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN) -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#endif - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* - * x86 supports only little-endian. - */ - if (byte_order != 0 && byte_order != __LITTLE_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - return as; -#endif -} diff --git a/contrib/libunwind/src/x86/Gget_proc_info.c b/contrib/libunwind/src/x86/Gget_proc_info.c deleted file mode 100644 index 45b4cd5bc12..00000000000 --- a/contrib/libunwind/src/x86/Gget_proc_info.c +++ /dev/null @@ -1,45 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) -{ - struct cursor *c = (struct cursor *) cursor; - - if (dwarf_make_proc_info (&c->dwarf) < 0) - { - /* On x86, it's relatively common to be missing DWARF unwind - info. We don't want to fail in that case, because the - frame-chain still would let us do a backtrace at least. */ - memset (pi, 0, sizeof (*pi)); - pi->start_ip = c->dwarf.ip; - pi->end_ip = c->dwarf.ip + 1; - return 0; - } - *pi = c->dwarf.pi; - return 0; -} diff --git a/contrib/libunwind/src/x86/Gget_save_loc.c b/contrib/libunwind/src/x86/Gget_save_loc.c deleted file mode 100644 index d440f9eca50..00000000000 --- a/contrib/libunwind/src/x86/Gget_save_loc.c +++ /dev/null @@ -1,133 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) -{ - struct cursor *c = (struct cursor *) cursor; - dwarf_loc_t loc; - - loc = DWARF_NULL_LOC; /* default to "not saved" */ - - switch (reg) - { - case UNW_X86_EIP: loc = c->dwarf.loc[EIP]; break; - case UNW_X86_CFA: break; - case UNW_X86_EAX: loc = c->dwarf.loc[EAX]; break; - case UNW_X86_ECX: loc = c->dwarf.loc[ECX]; break; - case UNW_X86_EDX: loc = c->dwarf.loc[EDX]; break; - case UNW_X86_EBX: loc = c->dwarf.loc[EBX]; break; - case UNW_X86_ESP: loc = c->dwarf.loc[ESP]; break; - case UNW_X86_EBP: loc = c->dwarf.loc[EBP]; break; - case UNW_X86_ESI: loc = c->dwarf.loc[ESI]; break; - case UNW_X86_EDI: loc = c->dwarf.loc[EDI]; break; - case UNW_X86_EFLAGS: loc = c->dwarf.loc[EFLAGS]; break; - case UNW_X86_TRAPNO: loc = c->dwarf.loc[TRAPNO]; break; - case UNW_X86_ST0: loc = c->dwarf.loc[ST0]; break; - - case UNW_X86_FCW: - case UNW_X86_FSW: - case UNW_X86_FTW: - case UNW_X86_FOP: - case UNW_X86_FCS: - case UNW_X86_FIP: - case UNW_X86_FEA: - case UNW_X86_FDS: - case UNW_X86_MXCSR: - case UNW_X86_GS: - case UNW_X86_FS: - case UNW_X86_ES: - case UNW_X86_DS: - case UNW_X86_SS: - case UNW_X86_CS: - case UNW_X86_TSS: - case UNW_X86_LDT: - loc = x86_scratch_loc (c, reg); - break; - - /* stacked fp registers */ - case UNW_X86_ST1: - case UNW_X86_ST2: - case UNW_X86_ST3: - case UNW_X86_ST4: - case UNW_X86_ST5: - case UNW_X86_ST6: - case UNW_X86_ST7: - /* SSE fp registers */ - case UNW_X86_XMM0_lo: - case UNW_X86_XMM0_hi: - case UNW_X86_XMM1_lo: - case UNW_X86_XMM1_hi: - case UNW_X86_XMM2_lo: - case UNW_X86_XMM2_hi: - case UNW_X86_XMM3_lo: - case UNW_X86_XMM3_hi: - case UNW_X86_XMM4_lo: - case UNW_X86_XMM4_hi: - case UNW_X86_XMM5_lo: - case UNW_X86_XMM5_hi: - case UNW_X86_XMM6_lo: - case UNW_X86_XMM6_hi: - case UNW_X86_XMM7_lo: - case UNW_X86_XMM7_hi: - case UNW_X86_XMM0: - case UNW_X86_XMM1: - case UNW_X86_XMM2: - case UNW_X86_XMM3: - case UNW_X86_XMM4: - case UNW_X86_XMM5: - case UNW_X86_XMM6: - case UNW_X86_XMM7: - loc = x86_scratch_loc (c, reg); - break; - - default: - break; - } - - memset (sloc, 0, sizeof (*sloc)); - - if (DWARF_IS_NULL_LOC (loc)) - { - sloc->type = UNW_SLT_NONE; - return 0; - } - -#if !defined(UNW_LOCAL_ONLY) - if (DWARF_IS_REG_LOC (loc)) - { - sloc->type = UNW_SLT_REG; - sloc->u.regnum = DWARF_GET_LOC (loc); - } - else -#endif - { - sloc->type = UNW_SLT_MEMORY; - sloc->u.addr = DWARF_GET_LOC (loc); - } - return 0; -} diff --git a/contrib/libunwind/src/x86/Gglobal.c b/contrib/libunwind/src/x86/Gglobal.c deleted file mode 100644 index 132b8249944..00000000000 --- a/contrib/libunwind/src/x86/Gglobal.c +++ /dev/null @@ -1,67 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "dwarf_i.h" - -HIDDEN define_lock (x86_lock); -HIDDEN int tdep_init_done; - -/* See comments for svr4_dbx_register_map[] in gcc/config/i386/i386.c. */ - -HIDDEN const uint8_t dwarf_to_unw_regnum_map[19] = - { - UNW_X86_EAX, UNW_X86_ECX, UNW_X86_EDX, UNW_X86_EBX, - UNW_X86_ESP, UNW_X86_EBP, UNW_X86_ESI, UNW_X86_EDI, - UNW_X86_EIP, UNW_X86_EFLAGS, UNW_X86_TRAPNO, - UNW_X86_ST0, UNW_X86_ST1, UNW_X86_ST2, UNW_X86_ST3, - UNW_X86_ST4, UNW_X86_ST5, UNW_X86_ST6, UNW_X86_ST7 - }; - -HIDDEN void -tdep_init (void) -{ - intrmask_t saved_mask; - - sigfillset (&unwi_full_mask); - - lock_acquire (&x86_lock, saved_mask); - { - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - mi_init (); - - dwarf_init (); - -#ifndef UNW_REMOTE_ONLY - x86_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - } - out: - lock_release (&x86_lock, saved_mask); -} diff --git a/contrib/libunwind/src/x86/Ginit.c b/contrib/libunwind/src/x86/Ginit.c deleted file mode 100644 index 876990fe1cd..00000000000 --- a/contrib/libunwind/src/x86/Ginit.c +++ /dev/null @@ -1,243 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002 Hewlett-Packard Co - Copyright (C) 2007 David Mosberger-Tang - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -PROTECTED unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; - -# ifdef UNW_LOCAL_ONLY - -HIDDEN void * -tdep_uc_addr (ucontext_t *uc, int reg) -{ - return x86_r_uc_addr (uc, reg); -} - -# endif /* UNW_LOCAL_ONLY */ - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - -/* XXX fix me: there is currently no way to locate the dyn-info list - by a remote unwinder. On ia64, this is done via a special - unwind-table entry. Perhaps something similar can be done with - DWARF2 unwind info. */ - -static void -put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ - *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; - return 0; -} - -#define PAGE_SIZE 4096 -#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1)) - -/* Cache of already validated addresses */ -#define NLGA 4 -static unw_word_t last_good_addr[NLGA]; -static int lga_victim; - -static int -validate_mem (unw_word_t addr) -{ - int i, victim; -#ifdef HAVE_MINCORE - unsigned char mvec[2]; /* Unaligned access may cross page boundary */ -#endif - size_t len; - - if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr)) - len = PAGE_SIZE; - else - len = PAGE_SIZE * 2; - - addr = PAGE_START(addr); - - if (addr == 0) - return -1; - - for (i = 0; i < NLGA; i++) - { - if (last_good_addr[i] && (addr == last_good_addr[i])) - return 0; - } - -#ifdef HAVE_MINCORE - if (mincore ((void *) addr, len, mvec) == -1) -#else - if (msync ((void *) addr, len, MS_ASYNC) == -1) -#endif - return -1; - - victim = lga_victim; - for (i = 0; i < NLGA; i++) { - if (!last_good_addr[victim]) { - last_good_addr[victim++] = addr; - return 0; - } - victim = (victim + 1) % NLGA; - } - - /* All slots full. Evict the victim. */ - last_good_addr[victim] = addr; - victim = (victim + 1) % NLGA; - lga_victim = victim; - - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - if (write) - { - Debug (16, "mem[%x] <- %x\n", addr, *val); - *(unw_word_t *) addr = *val; - } - else - { - /* validate address */ - const struct cursor *c = (const struct cursor *)arg; - if (c && c->validate && validate_mem(addr)) - return -1; - *val = *(unw_word_t *) addr; - Debug (16, "mem[%x] -> %x\n", addr, *val); - } - return 0; -} - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, - void *arg) -{ - unw_word_t *addr; - ucontext_t *uc = ((struct cursor *)arg)->uc; - - if (unw_is_fpreg (reg)) - goto badreg; - - if (!(addr = x86_r_uc_addr (uc, reg))) - goto badreg; - - if (write) - { - *(unw_word_t *) addr = *val; - Debug (12, "%s <- %x\n", unw_regname (reg), *val); - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "%s -> %x\n", unw_regname (reg), *val); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - ucontext_t *uc = ((struct cursor *)arg)->uc; - unw_fpreg_t *addr; - - if (!unw_is_fpreg (reg)) - goto badreg; - - if (!(addr = x86_r_uc_addr (uc, reg))) - goto badreg; - - if (write) - { - Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - *(unw_fpreg_t *) addr = *val; - } - else - { - *val = *(unw_fpreg_t *) addr; - Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - /* attempt to access a non-preserved register */ - return -UNW_EBADREG; -} - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - return _Uelf32_get_proc_name (as, getpid (), ip, buf, buf_len, offp); -} - -HIDDEN void -x86_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; - local_addr_space.acc.find_proc_info = dwarf_find_proc_info; - local_addr_space.acc.put_unwind_info = put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = x86_local_resume; - local_addr_space.acc.get_proc_name = get_static_proc_name; - unw_flush_cache (&local_addr_space, 0, 0); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/x86/Ginit_local.c b/contrib/libunwind/src/x86/Ginit_local.c deleted file mode 100644 index 88c52de3848..00000000000 --- a/contrib/libunwind/src/x86/Ginit_local.c +++ /dev/null @@ -1,79 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "init.h" - -#ifdef UNW_REMOTE_ONLY - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - return -UNW_EINVAL; -} - -#else /* !UNW_REMOTE_ONLY */ - -static int -unw_init_local_common(unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) -{ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = unw_local_addr_space; - c->dwarf.as_arg = c; - c->uc = uc; - c->validate = 0; - return common_init (c, use_prev_instr); -} - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - return unw_init_local_common(cursor, uc, 1); -} - -PROTECTED int -unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) -{ - if (!flag) - { - return unw_init_local_common(cursor, uc, 1); - } - else if (flag == UNW_INIT_SIGNAL_FRAME) - { - return unw_init_local_common(cursor, uc, 0); - } - else - { - return -UNW_EINVAL; - } -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/x86/Ginit_remote.c b/contrib/libunwind/src/x86/Ginit_remote.c deleted file mode 100644 index 16b63954418..00000000000 --- a/contrib/libunwind/src/x86/Ginit_remote.c +++ /dev/null @@ -1,56 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "init.h" -#include "unwind_i.h" - -PROTECTED int -unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) -{ -#ifdef UNW_LOCAL_ONLY - return -UNW_EINVAL; -#else /* !UNW_LOCAL_ONLY */ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = as; - c->dwarf.as_arg = as_arg; - if (as == unw_local_addr_space) - { - c->dwarf.as_arg = c; - c->uc = as_arg; - } - else - { - c->dwarf.as_arg = as_arg; - c->uc = 0; - } - return common_init (c, 0); -#endif /* !UNW_LOCAL_ONLY */ -} diff --git a/contrib/libunwind/src/x86/Gos-freebsd.c b/contrib/libunwind/src/x86/Gos-freebsd.c deleted file mode 100644 index cf05f0789d4..00000000000 --- a/contrib/libunwind/src/x86/Gos-freebsd.c +++ /dev/null @@ -1,374 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2010 Konstantin Belousov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include - -#include "unwind_i.h" -#include "offsets.h" - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, w1, w2, w3, w4, w5, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - /* Check if EIP points at sigreturn() sequence. It can be: -sigcode+4: from amd64 freebsd32 environment -8d 44 24 20 lea 0x20(%esp),%eax -50 push %eax -b8 a1 01 00 00 mov $0x1a1,%eax -50 push %eax -cd 80 int $0x80 - -sigcode+4: from real i386 -8d 44 24 20 lea 0x20(%esp),%eax -50 push %eax -f7 40 54 00 02 00 testl $0x20000,0x54(%eax) -75 03 jne sigcode+21 -8e 68 14 mov 0x14(%eax),%gs -b8 a1 01 00 00 mov $0x1a1,%eax -50 push %eax -cd 80 int $0x80 - -freebsd4_sigcode+4: -XXX -osigcode: -XXX - */ - ip = c->dwarf.ip; - ret = X86_SCF_NONE; - c->sigcontext_format = ret; - if ((*a->access_mem) (as, ip, &w0, 0, arg) < 0 || - (*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0 || - (*a->access_mem) (as, ip + 8, &w2, 0, arg) < 0 || - (*a->access_mem) (as, ip + 12, &w3, 0, arg) < 0) - return ret; - if (w0 == 0x2024448d && w1 == 0x01a1b850 && w2 == 0xcd500000 && - (w3 & 0xff) == 0x80) - ret = X86_SCF_FREEBSD_SIGFRAME; - else { - if ((*a->access_mem) (as, ip + 16, &w4, 0, arg) < 0 || - (*a->access_mem) (as, ip + 20, &w5, 0, arg) < 0) - return ret; - if (w0 == 0x2024448d && w1 == 0x5440f750 && w2 == 0x75000200 && - w3 == 0x14688e03 && w4 == 0x0001a1b8 && w5 == 0x80cd5000) - ret = X86_SCF_FREEBSD_SIGFRAME; - } - - /* Check for syscall */ - if (ret == X86_SCF_NONE && (*a->access_mem) (as, ip - 2, &w0, 0, arg) >= 0 && - (w0 & 0xffff) == 0x80cd) - ret = X86_SCF_FREEBSD_SYSCALL; - Debug (16, "returning %d\n", ret); - c->sigcontext_format = ret; - return (ret); -} - -PROTECTED int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) { - struct sigframe *sf; - uintptr_t uc_addr; - struct dwarf_loc esp_loc; - - sf = (struct sigframe *)c->dwarf.cfa; - uc_addr = (uintptr_t)&(sf->sf_uc); - c->sigcontext_addr = c->dwarf.cfa; - - esp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0); - ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa); - if (ret < 0) - { - Debug (2, "returning 0\n"); - return 0; - } - - c->dwarf.loc[EIP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EIP_OFF, 0); - c->dwarf.loc[ESP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0); - c->dwarf.loc[EAX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EAX_OFF, 0); - c->dwarf.loc[ECX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ECX_OFF, 0); - c->dwarf.loc[EDX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDX_OFF, 0); - c->dwarf.loc[EBX] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBX_OFF, 0); - c->dwarf.loc[EBP] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBP_OFF, 0); - c->dwarf.loc[ESI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESI_OFF, 0); - c->dwarf.loc[EDI] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EDI_OFF, 0); - c->dwarf.loc[EFLAGS] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EFLAGS_OFF, 0); - c->dwarf.loc[TRAPNO] = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_TRAPNO_OFF, 0); - c->dwarf.loc[ST0] = DWARF_NULL_LOC; - } else if (c->sigcontext_format == X86_SCF_FREEBSD_SYSCALL) { - c->dwarf.loc[EIP] = DWARF_LOC (c->dwarf.cfa, 0); - c->dwarf.loc[EAX] = DWARF_NULL_LOC; - c->dwarf.cfa += 4; - c->dwarf.use_prev_instr = 1; - } else { - Debug (8, "Gstep: not handling frame format %d\n", c->sigcontext_format); - abort(); - } - return 0; -} - -HIDDEN dwarf_loc_t -x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) -{ - unw_word_t addr = c->sigcontext_addr, off, xmm_off; - unw_word_t fpstate, fpformat; - int ret, is_fpstate = 0, is_xmmstate = 0; - - switch (c->sigcontext_format) - { - case X86_SCF_NONE: - return DWARF_REG_LOC (&c->dwarf, reg); - - case X86_SCF_FREEBSD_SIGFRAME: - addr += offsetof(struct sigframe, sf_uc) + FREEBSD_UC_MCONTEXT_OFF; - break; - - case X86_SCF_FREEBSD_SIGFRAME4: - abort(); - break; - - case X86_SCF_FREEBSD_OSIGFRAME: - /* XXXKIB */ - abort(); - break; - - case X86_SCF_FREEBSD_SYSCALL: - /* XXXKIB */ - abort(); - break; - - default: - /* XXXKIB */ - abort(); - break; - } - - off = 0; /* shut gcc warning */ - switch (reg) - { - case UNW_X86_GS: off = FREEBSD_UC_MCONTEXT_GS_OFF; break; - case UNW_X86_FS: off = FREEBSD_UC_MCONTEXT_FS_OFF; break; - case UNW_X86_ES: off = FREEBSD_UC_MCONTEXT_ES_OFF; break; - case UNW_X86_DS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break; - case UNW_X86_EDI: off = FREEBSD_UC_MCONTEXT_EDI_OFF; break; - case UNW_X86_ESI: off = FREEBSD_UC_MCONTEXT_ESI_OFF; break; - case UNW_X86_EBP: off = FREEBSD_UC_MCONTEXT_EBP_OFF; break; - case UNW_X86_ESP: off = FREEBSD_UC_MCONTEXT_ESP_OFF; break; - case UNW_X86_EBX: off = FREEBSD_UC_MCONTEXT_EBX_OFF; break; - case UNW_X86_EDX: off = FREEBSD_UC_MCONTEXT_EDX_OFF; break; - case UNW_X86_ECX: off = FREEBSD_UC_MCONTEXT_ECX_OFF; break; - case UNW_X86_EAX: off = FREEBSD_UC_MCONTEXT_EAX_OFF; break; - case UNW_X86_TRAPNO: off = FREEBSD_UC_MCONTEXT_TRAPNO_OFF; break; - case UNW_X86_EIP: off = FREEBSD_UC_MCONTEXT_EIP_OFF; break; - case UNW_X86_CS: off = FREEBSD_UC_MCONTEXT_CS_OFF; break; - case UNW_X86_EFLAGS: off = FREEBSD_UC_MCONTEXT_EFLAGS_OFF; break; - case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break; - - case UNW_X86_FCW: - is_fpstate = 1; - off = FREEBSD_UC_MCONTEXT_CW_OFF; - xmm_off = FREEBSD_UC_MCONTEXT_CW_XMM_OFF; - break; - case UNW_X86_FSW: - is_fpstate = 1; - off = FREEBSD_UC_MCONTEXT_SW_OFF; - xmm_off = FREEBSD_UC_MCONTEXT_SW_XMM_OFF; - break; - case UNW_X86_FTW: - is_fpstate = 1; - xmm_off = FREEBSD_UC_MCONTEXT_TAG_XMM_OFF; - off = FREEBSD_UC_MCONTEXT_TAG_OFF; - break; - case UNW_X86_FCS: - is_fpstate = 1; - off = FREEBSD_UC_MCONTEXT_CSSEL_OFF; - xmm_off = FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF; - break; - case UNW_X86_FIP: - is_fpstate = 1; - off = FREEBSD_UC_MCONTEXT_IPOFF_OFF; - xmm_off = FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF; - break; - case UNW_X86_FEA: - is_fpstate = 1; - off = FREEBSD_UC_MCONTEXT_DATAOFF_OFF; - xmm_off = FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF; - break; - case UNW_X86_FDS: - is_fpstate = 1; - off = FREEBSD_US_MCONTEXT_DATASEL_OFF; - xmm_off = FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF; - break; - case UNW_X86_MXCSR: - is_fpstate = 1; - is_xmmstate = 1; - xmm_off = FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF; - break; - - /* stacked fp registers */ - case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3: - case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7: - is_fpstate = 1; - off = FREEBSD_UC_MCONTEXT_ST0_OFF + 10*(reg - UNW_X86_ST0); - xmm_off = FREEBSD_UC_MCONTEXT_ST0_XMM_OFF + 10*(reg - UNW_X86_ST0); - break; - - /* SSE fp registers */ - case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi: - case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi: - case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi: - case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi: - case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi: - case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi: - case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi: - case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi: - is_fpstate = 1; - is_xmmstate = 1; - xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); - break; - case UNW_X86_XMM0: - case UNW_X86_XMM1: - case UNW_X86_XMM2: - case UNW_X86_XMM3: - case UNW_X86_XMM4: - case UNW_X86_XMM5: - case UNW_X86_XMM6: - case UNW_X86_XMM7: - is_fpstate = 1; - is_xmmstate = 1; - xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 16*(reg - UNW_X86_XMM0); - break; - - case UNW_X86_FOP: - case UNW_X86_TSS: - case UNW_X86_LDT: - default: - return DWARF_REG_LOC (&c->dwarf, reg); - } - - if (is_fpstate) - { - if ((ret = dwarf_get (&c->dwarf, - DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPSTATE_OFF), - &fpstate)) < 0) - return DWARF_NULL_LOC; - if (fpstate == FREEBSD_UC_MCONTEXT_FPOWNED_NONE) - return DWARF_NULL_LOC; - if ((ret = dwarf_get (&c->dwarf, - DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPFORMAT_OFF), - &fpformat)) < 0) - return DWARF_NULL_LOC; - if (fpformat == FREEBSD_UC_MCONTEXT_FPFMT_NODEV || - (is_xmmstate && fpformat != FREEBSD_UC_MCONTEXT_FPFMT_XMM)) - return DWARF_NULL_LOC; - if (is_xmmstate) - off = xmm_off; - } - - return DWARF_MEM_LOC (c, addr + off); -} - -#ifndef UNW_REMOTE_ONLY -HIDDEN void * -x86_r_uc_addr (ucontext_t *uc, int reg) -{ - void *addr; - - switch (reg) - { - case UNW_X86_GS: addr = &uc->uc_mcontext.mc_gs; break; - case UNW_X86_FS: addr = &uc->uc_mcontext.mc_fs; break; - case UNW_X86_ES: addr = &uc->uc_mcontext.mc_es; break; - case UNW_X86_DS: addr = &uc->uc_mcontext.mc_ds; break; - case UNW_X86_EAX: addr = &uc->uc_mcontext.mc_eax; break; - case UNW_X86_EBX: addr = &uc->uc_mcontext.mc_ebx; break; - case UNW_X86_ECX: addr = &uc->uc_mcontext.mc_ecx; break; - case UNW_X86_EDX: addr = &uc->uc_mcontext.mc_edx; break; - case UNW_X86_ESI: addr = &uc->uc_mcontext.mc_esi; break; - case UNW_X86_EDI: addr = &uc->uc_mcontext.mc_edi; break; - case UNW_X86_EBP: addr = &uc->uc_mcontext.mc_ebp; break; - case UNW_X86_EIP: addr = &uc->uc_mcontext.mc_eip; break; - case UNW_X86_ESP: addr = &uc->uc_mcontext.mc_esp; break; - case UNW_X86_TRAPNO: addr = &uc->uc_mcontext.mc_trapno; break; - case UNW_X86_CS: addr = &uc->uc_mcontext.mc_cs; break; - case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.mc_eflags; break; - case UNW_X86_SS: addr = &uc->uc_mcontext.mc_ss; break; - - default: - addr = NULL; - } - return addr; -} - -HIDDEN int -x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ - struct cursor *c = (struct cursor *) cursor; - ucontext_t *uc = c->uc; - - /* Ensure c->pi is up-to-date. On x86, it's relatively common to be - missing DWARF unwind info. We don't want to fail in that case, - because the frame-chain still would let us do a backtrace at - least. */ - dwarf_make_proc_info (&c->dwarf); - - if (c->sigcontext_format == X86_SCF_NONE) { - Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); - setcontext (uc); - abort(); - } else if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) { - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - - Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); - sigreturn((ucontext_t *)((const char *)sc + FREEBSD_SC_UCONTEXT_OFF)); - abort(); - } else { - Debug (8, "resuming at ip=%x for sigcontext format %d not implemented\n", - c->dwarf.ip, c->sigcontext_format); - abort(); - } - return -UNW_EINVAL; -} - -#endif diff --git a/contrib/libunwind/src/x86/Gos-linux.c b/contrib/libunwind/src/x86/Gos-linux.c deleted file mode 100644 index 37a22b97b2f..00000000000 --- a/contrib/libunwind/src/x86/Gos-linux.c +++ /dev/null @@ -1,329 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, w1, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - /* Check if EIP points at sigreturn() sequence. On Linux, this is: - - __restore: - 0x58 pop %eax - 0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax - 0xcd 0x80 int 0x80 - - without SA_SIGINFO, and - - __restore_rt: - 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax - 0xcd 0x80 int 0x80 - 0x00 - - if SA_SIGINFO is specified. - */ - ip = c->dwarf.ip; - if ((*a->access_mem) (as, ip, &w0, 0, arg) < 0 - || (*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0) - ret = 0; - else - ret = ((w0 == 0x0077b858 && w1 == 0x80cd0000) - || (w0 == 0x0000adb8 && (w1 & 0xffffff) == 0x80cd00)); - Debug (16, "returning %d\n", ret); - return ret; -} - -PROTECTED int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - /* c->esp points at the arguments to the handler. Without - SA_SIGINFO, the arguments consist of a signal number - followed by a struct sigcontext. With SA_SIGINFO, the - arguments consist a signal number, a siginfo *, and a - ucontext *. */ - unw_word_t sc_addr; - unw_word_t siginfo_ptr_addr = c->dwarf.cfa + 4; - unw_word_t sigcontext_ptr_addr = c->dwarf.cfa + 8; - unw_word_t siginfo_ptr, sigcontext_ptr; - struct dwarf_loc esp_loc, siginfo_ptr_loc, sigcontext_ptr_loc; - - siginfo_ptr_loc = DWARF_LOC (siginfo_ptr_addr, 0); - sigcontext_ptr_loc = DWARF_LOC (sigcontext_ptr_addr, 0); - ret = (dwarf_get (&c->dwarf, siginfo_ptr_loc, &siginfo_ptr) - | dwarf_get (&c->dwarf, sigcontext_ptr_loc, &sigcontext_ptr)); - if (ret < 0) - { - Debug (2, "returning 0\n"); - return 0; - } - if (siginfo_ptr < c->dwarf.cfa - || siginfo_ptr > c->dwarf.cfa + 256 - || sigcontext_ptr < c->dwarf.cfa - || sigcontext_ptr > c->dwarf.cfa + 256) - { - /* Not plausible for SA_SIGINFO signal */ - c->sigcontext_format = X86_SCF_LINUX_SIGFRAME; - c->sigcontext_addr = sc_addr = c->dwarf.cfa + 4; - } - else - { - /* If SA_SIGINFO were not specified, we actually read - various segment pointers instead. We believe that at - least fs and _fsh are always zero for linux, so it is - not just unlikely, but impossible that we would end - up here. */ - c->sigcontext_format = X86_SCF_LINUX_RT_SIGFRAME; - c->sigcontext_addr = sigcontext_ptr; - sc_addr = sigcontext_ptr + LINUX_UC_MCONTEXT_OFF; - } - esp_loc = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0); - ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa); - if (ret < 0) - { - Debug (2, "returning 0\n"); - return 0; - } - - c->dwarf.loc[EAX] = DWARF_LOC (sc_addr + LINUX_SC_EAX_OFF, 0); - c->dwarf.loc[ECX] = DWARF_LOC (sc_addr + LINUX_SC_ECX_OFF, 0); - c->dwarf.loc[EDX] = DWARF_LOC (sc_addr + LINUX_SC_EDX_OFF, 0); - c->dwarf.loc[EBX] = DWARF_LOC (sc_addr + LINUX_SC_EBX_OFF, 0); - c->dwarf.loc[EBP] = DWARF_LOC (sc_addr + LINUX_SC_EBP_OFF, 0); - c->dwarf.loc[ESI] = DWARF_LOC (sc_addr + LINUX_SC_ESI_OFF, 0); - c->dwarf.loc[EDI] = DWARF_LOC (sc_addr + LINUX_SC_EDI_OFF, 0); - c->dwarf.loc[EFLAGS] = DWARF_NULL_LOC; - c->dwarf.loc[TRAPNO] = DWARF_NULL_LOC; - c->dwarf.loc[ST0] = DWARF_NULL_LOC; - c->dwarf.loc[EIP] = DWARF_LOC (sc_addr + LINUX_SC_EIP_OFF, 0); - c->dwarf.loc[ESP] = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0); - - return 0; -} - -HIDDEN dwarf_loc_t -x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) -{ - unw_word_t addr = c->sigcontext_addr, fpstate_addr, off; - int ret, is_fpstate = 0; - - switch (c->sigcontext_format) - { - case X86_SCF_NONE: - return DWARF_REG_LOC (&c->dwarf, reg); - - case X86_SCF_LINUX_SIGFRAME: - break; - - case X86_SCF_LINUX_RT_SIGFRAME: - addr += LINUX_UC_MCONTEXT_OFF; - break; - - default: - return DWARF_NULL_LOC; - } - - switch (reg) - { - case UNW_X86_GS: off = LINUX_SC_GS_OFF; break; - case UNW_X86_FS: off = LINUX_SC_FS_OFF; break; - case UNW_X86_ES: off = LINUX_SC_ES_OFF; break; - case UNW_X86_DS: off = LINUX_SC_DS_OFF; break; - case UNW_X86_EDI: off = LINUX_SC_EDI_OFF; break; - case UNW_X86_ESI: off = LINUX_SC_ESI_OFF; break; - case UNW_X86_EBP: off = LINUX_SC_EBP_OFF; break; - case UNW_X86_ESP: off = LINUX_SC_ESP_OFF; break; - case UNW_X86_EBX: off = LINUX_SC_EBX_OFF; break; - case UNW_X86_EDX: off = LINUX_SC_EDX_OFF; break; - case UNW_X86_ECX: off = LINUX_SC_ECX_OFF; break; - case UNW_X86_EAX: off = LINUX_SC_EAX_OFF; break; - case UNW_X86_TRAPNO: off = LINUX_SC_TRAPNO_OFF; break; - case UNW_X86_EIP: off = LINUX_SC_EIP_OFF; break; - case UNW_X86_CS: off = LINUX_SC_CS_OFF; break; - case UNW_X86_EFLAGS: off = LINUX_SC_EFLAGS_OFF; break; - case UNW_X86_SS: off = LINUX_SC_SS_OFF; break; - - /* The following is probably not correct for all possible cases. - Somebody who understands this better should review this for - correctness. */ - - case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break; - case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break; - case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break; - case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break; - case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break; - case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break; - case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break; - case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break; - - /* stacked fp registers */ - case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3: - case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7: - is_fpstate = 1; - off = LINUX_FPSTATE_ST0_OFF + 10*(reg - UNW_X86_ST0); - break; - - /* SSE fp registers */ - case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi: - case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi: - case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi: - case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi: - case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi: - case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi: - case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi: - case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi: - is_fpstate = 1; - off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); - break; - case UNW_X86_XMM0: - case UNW_X86_XMM1: - case UNW_X86_XMM2: - case UNW_X86_XMM3: - case UNW_X86_XMM4: - case UNW_X86_XMM5: - case UNW_X86_XMM6: - case UNW_X86_XMM7: - is_fpstate = 1; - off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0); - break; - - case UNW_X86_FOP: - case UNW_X86_TSS: - case UNW_X86_LDT: - default: - return DWARF_REG_LOC (&c->dwarf, reg); - } - - if (is_fpstate) - { - if ((ret = dwarf_get (&c->dwarf, - DWARF_MEM_LOC (&c->dwarf, - addr + LINUX_SC_FPSTATE_OFF), - &fpstate_addr)) < 0) - return DWARF_NULL_LOC; - - if (!fpstate_addr) - return DWARF_NULL_LOC; - - return DWARF_MEM_LOC (c, fpstate_addr + off); - } - else - return DWARF_MEM_LOC (c, addr + off); -} - -#ifndef UNW_REMOTE_ONLY -HIDDEN void * -x86_r_uc_addr (ucontext_t *uc, int reg) -{ - void *addr; - - switch (reg) - { - case UNW_X86_GS: addr = &uc->uc_mcontext.gregs[REG_GS]; break; - case UNW_X86_FS: addr = &uc->uc_mcontext.gregs[REG_FS]; break; - case UNW_X86_ES: addr = &uc->uc_mcontext.gregs[REG_ES]; break; - case UNW_X86_DS: addr = &uc->uc_mcontext.gregs[REG_DS]; break; - case UNW_X86_EAX: addr = &uc->uc_mcontext.gregs[REG_EAX]; break; - case UNW_X86_EBX: addr = &uc->uc_mcontext.gregs[REG_EBX]; break; - case UNW_X86_ECX: addr = &uc->uc_mcontext.gregs[REG_ECX]; break; - case UNW_X86_EDX: addr = &uc->uc_mcontext.gregs[REG_EDX]; break; - case UNW_X86_ESI: addr = &uc->uc_mcontext.gregs[REG_ESI]; break; - case UNW_X86_EDI: addr = &uc->uc_mcontext.gregs[REG_EDI]; break; - case UNW_X86_EBP: addr = &uc->uc_mcontext.gregs[REG_EBP]; break; - case UNW_X86_EIP: addr = &uc->uc_mcontext.gregs[REG_EIP]; break; - case UNW_X86_ESP: addr = &uc->uc_mcontext.gregs[REG_ESP]; break; - case UNW_X86_TRAPNO: addr = &uc->uc_mcontext.gregs[REG_TRAPNO]; break; - case UNW_X86_CS: addr = &uc->uc_mcontext.gregs[REG_CS]; break; - case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.gregs[REG_EFL]; break; - case UNW_X86_SS: addr = &uc->uc_mcontext.gregs[REG_SS]; break; - - default: - addr = NULL; - } - return addr; -} - -HIDDEN int -x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ - struct cursor *c = (struct cursor *) cursor; - ucontext_t *uc = c->uc; - - /* Ensure c->pi is up-to-date. On x86, it's relatively common to be - missing DWARF unwind info. We don't want to fail in that case, - because the frame-chain still would let us do a backtrace at - least. */ - dwarf_make_proc_info (&c->dwarf); - - if (unlikely (c->sigcontext_format != X86_SCF_NONE)) - { - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - - Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); - x86_sigreturn (sc); - } - else - { - Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); - setcontext (uc); - } - return -UNW_EINVAL; -} - -/* sigreturn() is a no-op on x86 glibc. */ -HIDDEN void -x86_sigreturn (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - mcontext_t *sc_mcontext = &((struct ucontext*)sc)->uc_mcontext; - /* Copy in saved uc - all preserved regs are at the start of sigcontext */ - memcpy(sc_mcontext, &c->uc->uc_mcontext, - DWARF_NUM_PRESERVED_REGS * sizeof(unw_word_t)); - - Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", - (unsigned long long) c->dwarf.ip, sc); - __asm__ __volatile__ ("mov %0, %%esp;" - "mov %1, %%eax;" - "syscall" - :: "r"(sc), "i"(SYS_rt_sigreturn) - : "memory"); - abort(); -} -#endif diff --git a/contrib/libunwind/src/x86/Greg_states_iterate.c b/contrib/libunwind/src/x86/Greg_states_iterate.c deleted file mode 100644 index a39837a1781..00000000000 --- a/contrib/libunwind/src/x86/Greg_states_iterate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_reg_states_iterate (&c->dwarf, cb, token); -} diff --git a/contrib/libunwind/src/x86/Gregs.c b/contrib/libunwind/src/x86/Gregs.c deleted file mode 100644 index 4a9592617d0..00000000000 --- a/contrib/libunwind/src/x86/Gregs.c +++ /dev/null @@ -1,178 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "offsets.h" -#include "unwind_i.h" - -HIDDEN dwarf_loc_t -x86_scratch_loc (struct cursor *c, unw_regnum_t reg) -{ - if (c->sigcontext_addr) - return x86_get_scratch_loc (c, reg); - else - return DWARF_REG_LOC (&c->dwarf, reg); -} - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - dwarf_loc_t loc = DWARF_NULL_LOC; - unsigned int mask; - int arg_num; - - switch (reg) - { - - case UNW_X86_EIP: - if (write) - c->dwarf.ip = *valp; /* also update the EIP cache */ - loc = c->dwarf.loc[EIP]; - break; - - case UNW_X86_CFA: - case UNW_X86_ESP: - if (write) - return -UNW_EREADONLYREG; - *valp = c->dwarf.cfa; - return 0; - - case UNW_X86_EAX: - case UNW_X86_EDX: - arg_num = reg - UNW_X86_EAX; - mask = (1 << arg_num); - if (write) - { - c->dwarf.eh_args[arg_num] = *valp; - c->dwarf.eh_valid_mask |= mask; - return 0; - } - else if ((c->dwarf.eh_valid_mask & mask) != 0) - { - *valp = c->dwarf.eh_args[arg_num]; - return 0; - } - else - loc = c->dwarf.loc[(reg == UNW_X86_EAX) ? EAX : EDX]; - break; - - case UNW_X86_ECX: loc = c->dwarf.loc[ECX]; break; - case UNW_X86_EBX: loc = c->dwarf.loc[EBX]; break; - - case UNW_X86_EBP: loc = c->dwarf.loc[EBP]; break; - case UNW_X86_ESI: loc = c->dwarf.loc[ESI]; break; - case UNW_X86_EDI: loc = c->dwarf.loc[EDI]; break; - case UNW_X86_EFLAGS: loc = c->dwarf.loc[EFLAGS]; break; - case UNW_X86_TRAPNO: loc = c->dwarf.loc[TRAPNO]; break; - - case UNW_X86_FCW: - case UNW_X86_FSW: - case UNW_X86_FTW: - case UNW_X86_FOP: - case UNW_X86_FCS: - case UNW_X86_FIP: - case UNW_X86_FEA: - case UNW_X86_FDS: - case UNW_X86_MXCSR: - case UNW_X86_GS: - case UNW_X86_FS: - case UNW_X86_ES: - case UNW_X86_DS: - case UNW_X86_SS: - case UNW_X86_CS: - case UNW_X86_TSS: - case UNW_X86_LDT: - loc = x86_scratch_loc (c, reg); - break; - - default: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; - } - - if (write) - return dwarf_put (&c->dwarf, loc, *valp); - else - return dwarf_get (&c->dwarf, loc, valp); -} - -HIDDEN int -tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, - int write) -{ - struct dwarf_loc loc = DWARF_NULL_LOC; - - switch (reg) - { - case UNW_X86_ST0: - loc = c->dwarf.loc[ST0]; - break; - - /* stacked fp registers */ - case UNW_X86_ST1: - case UNW_X86_ST2: - case UNW_X86_ST3: - case UNW_X86_ST4: - case UNW_X86_ST5: - case UNW_X86_ST6: - case UNW_X86_ST7: - /* SSE fp registers */ - case UNW_X86_XMM0: - case UNW_X86_XMM1: - case UNW_X86_XMM2: - case UNW_X86_XMM3: - case UNW_X86_XMM4: - case UNW_X86_XMM5: - case UNW_X86_XMM6: - case UNW_X86_XMM7: - case UNW_X86_XMM0_lo: - case UNW_X86_XMM0_hi: - case UNW_X86_XMM1_lo: - case UNW_X86_XMM1_hi: - case UNW_X86_XMM2_lo: - case UNW_X86_XMM2_hi: - case UNW_X86_XMM3_lo: - case UNW_X86_XMM3_hi: - case UNW_X86_XMM4_lo: - case UNW_X86_XMM4_hi: - case UNW_X86_XMM5_lo: - case UNW_X86_XMM5_hi: - case UNW_X86_XMM6_lo: - case UNW_X86_XMM6_hi: - case UNW_X86_XMM7_lo: - case UNW_X86_XMM7_hi: - loc = x86_scratch_loc (c, reg); - break; - - default: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; - } - - if (write) - return dwarf_putfp (&c->dwarf, loc, *valp); - else - return dwarf_getfp (&c->dwarf, loc, valp); -} diff --git a/contrib/libunwind/src/x86/Gresume.c b/contrib/libunwind/src/x86/Gresume.c deleted file mode 100644 index 77a586adbd5..00000000000 --- a/contrib/libunwind/src/x86/Gresume.c +++ /dev/null @@ -1,91 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" -#include "offsets.h" - -/* This routine is responsible for copying the register values in - cursor C and establishing them as the current machine state. */ - -static inline int -establish_machine_state (struct cursor *c) -{ - int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, - int write, void *); - int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, - int write, void *); - unw_addr_space_t as = c->dwarf.as; - void *arg = c->dwarf.as_arg; - unw_fpreg_t fpval; - unw_word_t val; - int reg; - - access_reg = as->acc.access_reg; - access_fpreg = as->acc.access_fpreg; - - Debug (8, "copying out cursor state\n"); - - for (reg = 0; reg <= UNW_REG_LAST; ++reg) - { - Debug (16, "copying %s %d\n", unw_regname (reg), reg); - if (unw_is_fpreg (reg)) - { - if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) - (*access_fpreg) (as, reg, &fpval, 1, arg); - } - else - { - if (tdep_access_reg (c, reg, &val, 0) >= 0) - (*access_reg) (as, reg, &val, 1, arg); - } - } - - if (c->dwarf.args_size) - { - if (tdep_access_reg (c, UNW_X86_ESP, &val, 0) >= 0) - { - val += c->dwarf.args_size; - (*access_reg) (as, UNW_X86_ESP, &val, 1, arg); - } - } - return 0; -} - -PROTECTED int -unw_resume (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - Debug (1, "(cursor=%p)\n", c); - - if ((ret = establish_machine_state (c)) < 0) - return ret; - - return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, - c->dwarf.as_arg); -} diff --git a/contrib/libunwind/src/x86/Gstep.c b/contrib/libunwind/src/x86/Gstep.c deleted file mode 100644 index 8cec72eff49..00000000000 --- a/contrib/libunwind/src/x86/Gstep.c +++ /dev/null @@ -1,115 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" - -PROTECTED int -unw_step (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret, i; - - Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip); - - /* Try DWARF-based unwinding... */ - ret = dwarf_step (&c->dwarf); - - if (ret < 0 && ret != -UNW_ENOINFO) - { - Debug (2, "returning %d\n", ret); - return ret; - } - - if (unlikely (ret < 0)) - { - /* DWARF failed, let's see if we can follow the frame-chain - or skip over the signal trampoline. */ - struct dwarf_loc ebp_loc, eip_loc; - - /* We could get here because of missing/bad unwind information. - Validate all addresses before dereferencing. */ - c->validate = 1; - - Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); - - if (unw_is_signal_frame (cursor) > 0) - { - ret = unw_handle_signal_frame(cursor); - if (ret < 0) - { - Debug (2, "returning 0\n"); - return 0; - } - } - else - { - ret = dwarf_get (&c->dwarf, c->dwarf.loc[EBP], &c->dwarf.cfa); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - - Debug (13, "[EBP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EBP]), - c->dwarf.cfa); - - ebp_loc = DWARF_LOC (c->dwarf.cfa, 0); - eip_loc = DWARF_LOC (c->dwarf.cfa + 4, 0); - c->dwarf.cfa += 8; - - /* Mark all registers unsaved, since we don't know where - they are saved (if at all), except for the EBP and - EIP. */ - for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - - c->dwarf.loc[EBP] = ebp_loc; - c->dwarf.loc[EIP] = eip_loc; - c->dwarf.use_prev_instr = 1; - } - - if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP])) - { - ret = dwarf_get (&c->dwarf, c->dwarf.loc[EIP], &c->dwarf.ip); - if (ret < 0) - { - Debug (13, "dwarf_get([EIP=0x%x]) failed\n", DWARF_GET_LOC (c->dwarf.loc[EIP])); - Debug (2, "returning %d\n", ret); - return ret; - } - else - { - Debug (13, "[EIP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EIP]), - c->dwarf.ip); - } - } - else - c->dwarf.ip = 0; - } - ret = (c->dwarf.ip == 0) ? 0 : 1; - Debug (2, "returning %d\n", ret); - return ret; -} diff --git a/contrib/libunwind/src/x86/Lapply_reg_state.c b/contrib/libunwind/src/x86/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/x86/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/x86/Lcreate_addr_space.c b/contrib/libunwind/src/x86/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901..00000000000 --- a/contrib/libunwind/src/x86/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/contrib/libunwind/src/x86/Lget_proc_info.c b/contrib/libunwind/src/x86/Lget_proc_info.c deleted file mode 100644 index 69028b019fc..00000000000 --- a/contrib/libunwind/src/x86/Lget_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info.c" -#endif diff --git a/contrib/libunwind/src/x86/Lget_save_loc.c b/contrib/libunwind/src/x86/Lget_save_loc.c deleted file mode 100644 index 9ea048a9076..00000000000 --- a/contrib/libunwind/src/x86/Lget_save_loc.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_save_loc.c" -#endif diff --git a/contrib/libunwind/src/x86/Lglobal.c b/contrib/libunwind/src/x86/Lglobal.c deleted file mode 100644 index 6d7b489e14b..00000000000 --- a/contrib/libunwind/src/x86/Lglobal.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/contrib/libunwind/src/x86/Linit.c b/contrib/libunwind/src/x86/Linit.c deleted file mode 100644 index e9abfdd46a3..00000000000 --- a/contrib/libunwind/src/x86/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/contrib/libunwind/src/x86/Linit_local.c b/contrib/libunwind/src/x86/Linit_local.c deleted file mode 100644 index 68a1687e854..00000000000 --- a/contrib/libunwind/src/x86/Linit_local.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_local.c" -#endif diff --git a/contrib/libunwind/src/x86/Linit_remote.c b/contrib/libunwind/src/x86/Linit_remote.c deleted file mode 100644 index 58cb04ab7cd..00000000000 --- a/contrib/libunwind/src/x86/Linit_remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_remote.c" -#endif diff --git a/contrib/libunwind/src/x86/Los-freebsd.c b/contrib/libunwind/src/x86/Los-freebsd.c deleted file mode 100644 index a75a205df19..00000000000 --- a/contrib/libunwind/src/x86/Los-freebsd.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gos-freebsd.c" -#endif diff --git a/contrib/libunwind/src/x86/Los-linux.c b/contrib/libunwind/src/x86/Los-linux.c deleted file mode 100644 index 3cc18aabcc3..00000000000 --- a/contrib/libunwind/src/x86/Los-linux.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gos-linux.c" -#endif diff --git a/contrib/libunwind/src/x86/Lreg_states_iterate.c b/contrib/libunwind/src/x86/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/x86/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/x86/Lregs.c b/contrib/libunwind/src/x86/Lregs.c deleted file mode 100644 index 2c9c75cd7d9..00000000000 --- a/contrib/libunwind/src/x86/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/contrib/libunwind/src/x86/Lresume.c b/contrib/libunwind/src/x86/Lresume.c deleted file mode 100644 index 41a8cf003de..00000000000 --- a/contrib/libunwind/src/x86/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/contrib/libunwind/src/x86/Lstep.c b/contrib/libunwind/src/x86/Lstep.c deleted file mode 100644 index c1ac3c7547f..00000000000 --- a/contrib/libunwind/src/x86/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/contrib/libunwind/src/x86/getcontext-freebsd.S b/contrib/libunwind/src/x86/getcontext-freebsd.S deleted file mode 100644 index 670eff1ae17..00000000000 --- a/contrib/libunwind/src/x86/getcontext-freebsd.S +++ /dev/null @@ -1,112 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2010 Konstantin Belousov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "offsets.h" - - .global _Ux86_getcontext - .type _Ux86_getcontext, @function -_Ux86_getcontext: - .cfi_startproc - pushl %eax - .cfi_adjust_cfa_offset 4 - mov 8(%esp),%eax /* ucontext_t* */ - popl FREEBSD_UC_MCONTEXT_EAX_OFF(%eax) - .cfi_adjust_cfa_offset 4 - movl %ebx, FREEBSD_UC_MCONTEXT_EBX_OFF(%eax) - movl %ecx, FREEBSD_UC_MCONTEXT_ECX_OFF(%eax) - movl %edx, FREEBSD_UC_MCONTEXT_EDX_OFF(%eax) - movl %edi, FREEBSD_UC_MCONTEXT_EDI_OFF(%eax) - movl %esi, FREEBSD_UC_MCONTEXT_ESI_OFF(%eax) - movl %ebp, FREEBSD_UC_MCONTEXT_EBP_OFF(%eax) - - movl (%esp), %ecx - movl %ecx, FREEBSD_UC_MCONTEXT_EIP_OFF(%eax) - - leal 4(%esp), %ecx /* Exclude the return address. */ - movl %ecx, FREEBSD_UC_MCONTEXT_ESP_OFF(%eax) - - xorl %ecx, %ecx - movw %fs, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_FS_OFF(%eax) - movw %gs, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_GS_OFF(%eax) - movw %ds, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_DS_OFF(%eax) - movw %es, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_ES_OFF(%eax) - movw %ss, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_SS_OFF(%eax) - movw %cs, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_CS_OFF(%eax) - - pushfl - .cfi_adjust_cfa_offset 4 - popl FREEBSD_UC_MCONTEXT_EFLAGS_OFF(%eax) - .cfi_adjust_cfa_offset -4 - - movl $0, FREEBSD_UC_MCONTEXT_TRAPNO_OFF(%eax) - - movl $FREEBSD_UC_MCONTEXT_FPOWNED_FPU,\ - FREEBSD_UC_MCONTEXT_OWNEDFP_OFF(%eax) - movl $FREEBSD_UC_MCONTEXT_FPFMT_XMM,\ - FREEBSD_UC_MCONTEXT_FPFORMAT_OFF(%eax) - - /* - * Require CPU with fxsave implemented, and enabled by OS. - * - * If passed ucontext is not aligned to 16-byte boundary, - * save fpu context into temporary aligned location on stack - * and then copy. - */ - leal FREEBSD_UC_MCONTEXT_FPSTATE_OFF(%eax), %edx - testl $0xf, %edx - jne 2f - fxsave (%edx) /* fast path, passed ucontext save area was aligned */ -1: movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL,\ - FREEBSD_UC_MCONTEXT_MC_LEN_OFF(%eax) - - xorl %eax, %eax - ret - -2: movl %edx, %edi /* not aligned, do the dance */ - subl $512 + 16, %esp /* save area and 16 bytes for alignment */ - .cfi_adjust_cfa_offset 512 + 16 - movl %esp, %edx - orl $0xf, %edx /* align *%edx to 16-byte up */ - incl %edx - fxsave (%edx) - movl %edx, %esi /* copy to the final destination */ - movl $512/4,%ecx - rep; movsl - addl $512 + 16, %esp /* restore the stack */ - .cfi_adjust_cfa_offset -512 - 16 - movl FREEBSD_UC_MCONTEXT_ESI_OFF(%eax), %esi - movl FREEBSD_UC_MCONTEXT_EDI_OFF(%eax), %edi - jmp 1b - - .cfi_endproc - .size _Ux86_getcontext, . - _Ux86_getcontext - - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits diff --git a/contrib/libunwind/src/x86/getcontext-linux.S b/contrib/libunwind/src/x86/getcontext-linux.S deleted file mode 100644 index c469dadbac6..00000000000 --- a/contrib/libunwind/src/x86/getcontext-linux.S +++ /dev/null @@ -1,74 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2009 Google, Inc - Contributed by Paul Pluzhnikov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "offsets.h" - -/* int _Ux86_getcontext (ucontext_t *ucp) - - Saves the machine context in UCP necessary for libunwind. - Unlike the libc implementation, we don't save the signal mask - and hence avoid the cost of a system call per unwind. - -*/ - - .global _Ux86_getcontext - .type _Ux86_getcontext, @function -_Ux86_getcontext: - .cfi_startproc - mov 4(%esp),%eax /* ucontext_t* */ - - /* EAX is not preserved. */ - movl $0, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EAX_OFF)(%eax) - - movl %ebx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBX_OFF)(%eax) - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ECX_OFF)(%eax) - movl %edx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDX_OFF)(%eax) - movl %edi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDI_OFF)(%eax) - movl %esi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESI_OFF)(%eax) - movl %ebp, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBP_OFF)(%eax) - - movl (%esp), %ecx - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EIP_OFF)(%eax) - - leal 4(%esp), %ecx /* Exclude the return address. */ - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESP_OFF)(%eax) - - /* glibc getcontext saves FS, but not GS */ - xorl %ecx, %ecx - movw %fs, %cx - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FS_OFF)(%eax) - - leal LINUX_UC_FPREGS_MEM_OFF(%eax), %ecx - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) - fnstenv (%ecx) - fldenv (%ecx) - - xor %eax, %eax - ret - .cfi_endproc - .size _Ux86_getcontext, . - _Ux86_getcontext - - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits diff --git a/contrib/libunwind/src/x86/init.h b/contrib/libunwind/src/x86/init.h deleted file mode 100644 index b0db8d337df..00000000000 --- a/contrib/libunwind/src/x86/init.h +++ /dev/null @@ -1,69 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static inline int -common_init (struct cursor *c, unsigned use_prev_instr) -{ - int ret, i; - - c->dwarf.loc[EAX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EAX); - c->dwarf.loc[ECX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_ECX); - c->dwarf.loc[EDX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EDX); - c->dwarf.loc[EBX] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EBX); - c->dwarf.loc[ESP] = DWARF_REG_LOC (&c->dwarf, UNW_X86_ESP); - c->dwarf.loc[EBP] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EBP); - c->dwarf.loc[ESI] = DWARF_REG_LOC (&c->dwarf, UNW_X86_ESI); - c->dwarf.loc[EDI] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EDI); - c->dwarf.loc[EIP] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EIP); - c->dwarf.loc[EFLAGS] = DWARF_REG_LOC (&c->dwarf, UNW_X86_EFLAGS); - c->dwarf.loc[TRAPNO] = DWARF_REG_LOC (&c->dwarf, UNW_X86_TRAPNO); - c->dwarf.loc[ST0] = DWARF_REG_LOC (&c->dwarf, UNW_X86_ST0); - for (i = ST0 + 1; i < DWARF_NUM_PRESERVED_REGS; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[EIP], &c->dwarf.ip); - if (ret < 0) - return ret; - - ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_X86_ESP), - &c->dwarf.cfa); - if (ret < 0) - return ret; - - c->sigcontext_format = X86_SCF_NONE; - c->sigcontext_addr = 0; - - c->dwarf.args_size = 0; - c->dwarf.stash_frames = 0; - c->dwarf.use_prev_instr = use_prev_instr; - c->dwarf.pi_valid = 0; - c->dwarf.pi_is_dynamic = 0; - c->dwarf.hint = 0; - c->dwarf.prev_rs = 0; - - return 0; -} diff --git a/contrib/libunwind/src/x86/is_fpreg.c b/contrib/libunwind/src/x86/is_fpreg.c deleted file mode 100644 index addf9bcafcd..00000000000 --- a/contrib/libunwind/src/x86/is_fpreg.c +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2004-2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_is_fpreg (int regnum) -{ - return ((regnum >= UNW_X86_ST0 && regnum <= UNW_X86_ST7) - || (regnum >= UNW_X86_XMM0_lo && regnum <= UNW_X86_XMM7_hi) - || (regnum >= UNW_X86_XMM0 && regnum <= UNW_X86_XMM7)); -} diff --git a/contrib/libunwind/src/x86/longjmp.S b/contrib/libunwind/src/x86/longjmp.S deleted file mode 100644 index 05173d0c109..00000000000 --- a/contrib/libunwind/src/x86/longjmp.S +++ /dev/null @@ -1,39 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - - .globl _UI_longjmp_cont - - .type _UI_longjmp_cont, @function -_UI_longjmp_cont: - .cfi_startproc - .cfi_register 8, 0 /* IP saved in EAX */ - push %eax /* push target IP as return address */ - .cfi_restore 8 - mov %edx, %eax /* set up return-value */ - ret - .cfi_endproc - .size _UI_siglongjmp_cont, .-_UI_longjmp_cont - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits diff --git a/contrib/libunwind/src/x86/offsets.h b/contrib/libunwind/src/x86/offsets.h deleted file mode 100644 index e5aec7f5888..00000000000 --- a/contrib/libunwind/src/x86/offsets.h +++ /dev/null @@ -1,140 +0,0 @@ -/* Linux-specific definitions: */ - -/* Define various structure offsets to simplify cross-compilation. */ - -/* Offsets for x86 Linux "ucontext_t": */ - -#define LINUX_UC_FLAGS_OFF 0x00 -#define LINUX_UC_LINK_OFF 0x04 -#define LINUX_UC_STACK_OFF 0x08 -#define LINUX_UC_MCONTEXT_OFF 0x14 -#define LINUX_UC_SIGMASK_OFF 0x6c -#define LINUX_UC_FPREGS_MEM_OFF 0xec - -/* The struct sigcontext is located at an offset of 4 - from the stack pointer in the signal frame. */ - -/* Offsets for x86 Linux "struct sigcontext": */ - -#define LINUX_SC_GS_OFF 0x00 -#define LINUX_SC_GSH_OFF 0x02 -#define LINUX_SC_FS_OFF 0x04 -#define LINUX_SC_FSH_OFF 0x06 -#define LINUX_SC_ES_OFF 0x08 -#define LINUX_SC_ESH_OFF 0x0a -#define LINUX_SC_DS_OFF 0x0c -#define LINUX_SC_DSH_OFF 0x0e -#define LINUX_SC_EDI_OFF 0x10 -#define LINUX_SC_ESI_OFF 0x14 -#define LINUX_SC_EBP_OFF 0x18 -#define LINUX_SC_ESP_OFF 0x1c -#define LINUX_SC_EBX_OFF 0x20 -#define LINUX_SC_EDX_OFF 0x24 -#define LINUX_SC_ECX_OFF 0x28 -#define LINUX_SC_EAX_OFF 0x2c -#define LINUX_SC_TRAPNO_OFF 0x30 -#define LINUX_SC_ERR_OFF 0x34 -#define LINUX_SC_EIP_OFF 0x38 -#define LINUX_SC_CS_OFF 0x3c -#define LINUX_SC_CSH_OFF 0x3e -#define LINUX_SC_EFLAGS_OFF 0x40 -#define LINUX_SC_ESP_AT_SIGNAL_OFF 0x44 -#define LINUX_SC_SS_OFF 0x48 -#define LINUX_SC_SSH_OFF 0x4a -#define LINUX_SC_FPSTATE_OFF 0x4c -#define LINUX_SC_OLDMASK_OFF 0x50 -#define LINUX_SC_CR2_OFF 0x54 - -/* Offsets for x86 Linux "struct _fpstate": */ - -#define LINUX_FPSTATE_CW_OFF 0x000 -#define LINUX_FPSTATE_SW_OFF 0x004 -#define LINUX_FPSTATE_TAG_OFF 0x008 -#define LINUX_FPSTATE_IPOFF_OFF 0x00c -#define LINUX_FPSTATE_CSSEL_OFF 0x010 -#define LINUX_FPSTATE_DATAOFF_OFF 0x014 -#define LINUX_FPSTATE_DATASEL_OFF 0x018 -#define LINUX_FPSTATE_ST0_OFF 0x01c -#define LINUX_FPSTATE_ST1_OFF 0x026 -#define LINUX_FPSTATE_ST2_OFF 0x030 -#define LINUX_FPSTATE_ST3_OFF 0x03a -#define LINUX_FPSTATE_ST4_OFF 0x044 -#define LINUX_FPSTATE_ST5_OFF 0x04e -#define LINUX_FPSTATE_ST6_OFF 0x058 -#define LINUX_FPSTATE_ST7_OFF 0x062 -#define LINUX_FPSTATE_STATUS_OFF 0x06c -#define LINUX_FPSTATE_MAGIC_OFF 0x06e -#define LINUX_FPSTATE_FXSR_ENV_OFF 0x070 -#define LINUX_FPSTATE_MXCSR_OFF 0x088 -#define LINUX_FPSTATE_FXSR_ST0_OFF 0x090 -#define LINUX_FPSTATE_FXSR_ST1_OFF 0x0a0 -#define LINUX_FPSTATE_FXSR_ST2_OFF 0x0b0 -#define LINUX_FPSTATE_FXSR_ST3_OFF 0x0c0 -#define LINUX_FPSTATE_FXSR_ST4_OFF 0x0d0 -#define LINUX_FPSTATE_FXSR_ST5_OFF 0x0e0 -#define LINUX_FPSTATE_FXSR_ST6_OFF 0x0f0 -#define LINUX_FPSTATE_FXSR_ST7_OFF 0x100 -#define LINUX_FPSTATE_XMM0_OFF 0x110 -#define LINUX_FPSTATE_XMM1_OFF 0x120 -#define LINUX_FPSTATE_XMM2_OFF 0x130 -#define LINUX_FPSTATE_XMM3_OFF 0x140 -#define LINUX_FPSTATE_XMM4_OFF 0x150 -#define LINUX_FPSTATE_XMM5_OFF 0x160 -#define LINUX_FPSTATE_XMM6_OFF 0x170 -#define LINUX_FPSTATE_XMM7_OFF 0x180 - -/* FreeBSD-specific definitions: */ - -#define FREEBSD_SC_UCONTEXT_OFF 0x20 -#define FREEBSD_UC_MCONTEXT_OFF 0x10 - -#define FREEBSD_UC_MCONTEXT_GS_OFF 0x14 -#define FREEBSD_UC_MCONTEXT_FS_OFF 0x18 -#define FREEBSD_UC_MCONTEXT_ES_OFF 0x1c -#define FREEBSD_UC_MCONTEXT_DS_OFF 0x20 -#define FREEBSD_UC_MCONTEXT_EDI_OFF 0x24 -#define FREEBSD_UC_MCONTEXT_ESI_OFF 0x28 -#define FREEBSD_UC_MCONTEXT_EBP_OFF 0x2c -#define FREEBSD_UC_MCONTEXT_EBX_OFF 0x34 -#define FREEBSD_UC_MCONTEXT_EDX_OFF 0x38 -#define FREEBSD_UC_MCONTEXT_ECX_OFF 0x3c -#define FREEBSD_UC_MCONTEXT_EAX_OFF 0x40 -#define FREEBSD_UC_MCONTEXT_TRAPNO_OFF 0x44 -#define FREEBSD_UC_MCONTEXT_EIP_OFF 0x4c -#define FREEBSD_UC_MCONTEXT_ESP_OFF 0x58 -#define FREEBSD_UC_MCONTEXT_CS_OFF 0x50 -#define FREEBSD_UC_MCONTEXT_EFLAGS_OFF 0x54 -#define FREEBSD_UC_MCONTEXT_SS_OFF 0x5c -#define FREEBSD_UC_MCONTEXT_MC_LEN_OFF 0x60 -#define FREEBSD_UC_MCONTEXT_FPFORMAT_OFF 0x64 -#define FREEBSD_UC_MCONTEXT_OWNEDFP_OFF 0x68 -#define FREEBSD_UC_MCONTEXT_FPSTATE_OFF 0x70 - -#define FREEBSD_UC_MCONTEXT_CW_OFF 0x70 -#define FREEBSD_UC_MCONTEXT_SW_OFF 0x74 -#define FREEBSD_UC_MCONTEXT_TAG_OFF 0x78 -#define FREEBSD_UC_MCONTEXT_IPOFF_OFF 0x7c -#define FREEBSD_UC_MCONTEXT_CSSEL_OFF 0x80 -#define FREEBSD_UC_MCONTEXT_DATAOFF_OFF 0x84 -#define FREEBSD_US_MCONTEXT_DATASEL_OFF 0x88 -#define FREEBSD_UC_MCONTEXT_ST0_OFF 0x8c - -#define FREEBSD_UC_MCONTEXT_CW_XMM_OFF 0x70 -#define FREEBSD_UC_MCONTEXT_SW_XMM_OFF 0x72 -#define FREEBSD_UC_MCONTEXT_TAG_XMM_OFF 0x74 -#define FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF 0x78 -#define FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF 0x7c -#define FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF 0x80 -#define FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF 0x84 -#define FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF 0x88 -#define FREEBSD_UC_MCONTEXT_ST0_XMM_OFF 0x90 -#define FREEBSD_UC_MCONTEXT_XMM0_OFF 0x110 - -#define FREEBSD_UC_MCONTEXT_MC_LEN_VAL 0x280 -#define FREEBSD_UC_MCONTEXT_FPFMT_NODEV 0x10000 -#define FREEBSD_UC_MCONTEXT_FPFMT_387 0x10001 -#define FREEBSD_UC_MCONTEXT_FPFMT_XMM 0x10002 -#define FREEBSD_UC_MCONTEXT_FPOWNED_NONE 0x20000 -#define FREEBSD_UC_MCONTEXT_FPOWNED_FPU 0x20001 -#define FREEBSD_UC_MCONTEXT_FPOWNED_PCB 0x20002 - diff --git a/contrib/libunwind/src/x86/regname.c b/contrib/libunwind/src/x86/regname.c deleted file mode 100644 index 2228510a219..00000000000 --- a/contrib/libunwind/src/x86/regname.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "unwind_i.h" - -static const char *regname[] = - { - "eax", "edx", "ecx", "ebx", "esi", "edi", "ebp", "esp", "eip", - "eflags", "trapno", - "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7", - "fcw", "fsw", "ftw", "fop", "fcs", "fip", "fea", "fds", - "xmm0_lo", "xmm0_hi", "xmm1_lo", "xmm1_hi", - "xmm2_lo", "xmm2_hi", "xmm3_lo", "xmm3_hi", - "xmm4_lo", "xmm4_hi", "xmm5_lo", "xmm5_hi", - "xmm6_lo", "xmm6_hi", "xmm7_lo", "xmm7_hi", - "mxcsr", - "gs", "fs", "es", "ds", "ss", "cs", - "tss", "ldt", - "cfi", - "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", - }; - -PROTECTED const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) - return regname[reg]; - else - return "???"; -} diff --git a/contrib/libunwind/src/x86/siglongjmp.S b/contrib/libunwind/src/x86/siglongjmp.S deleted file mode 100644 index 32bba3b3b69..00000000000 --- a/contrib/libunwind/src/x86/siglongjmp.S +++ /dev/null @@ -1,92 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - Copyright (C) 2011 Konstantin Belousov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - - .globl _UI_siglongjmp_cont - -#if defined(__linux__) -#define SIG_SETMASK 2 -#elif defined(__FreeBSD__) -#define SIG_SETMASK 3 -#endif - - /* Stack layout at this point: - - +------------+ <- original $esp (at time of setjmp() call) - | sigmask[1] | - +------------+ - | sigmask[0] | - +------------+ - */ - - .type _UI_siglongjmp_cont, @function -_UI_siglongjmp_cont: - .cfi_startproc -#ifdef __linux__ - .cfi_register 8, 0 /* IP saved in EAX */ - .cfi_def_cfa_offset 8 - mov %esp, %ecx /* pass address of signal mask in 3rd sc arg */ - push %eax /* save target IP */ - .cfi_adjust_cfa_offset 4 - .cfi_offset 8, -12 - push %edx /* save return value */ - .cfi_adjust_cfa_offset 4 - push %ebx /* save %ebx (preserved) */ - .cfi_adjust_cfa_offset 4 - .cfi_offset 3, -20 - mov $SIG_SETMASK, %ebx /* 1st syscall arg (how) */ - xor %edx, %edx /* pass NULL as 3rd syscall arg (old maskp) */ - int $0x80 - pop %ebx /* restore %ebx */ - .cfi_adjust_cfa_offset -4 - .cfi_restore 3 - pop %eax /* fetch return value */ - .cfi_adjust_cfa_offset -4 - pop %edx /* pop target IP */ - .cfi_adjust_cfa_offset -4 - .cfi_register 8, 2 /* saved IP is now n EDX */ - lea 8(%esp), %esp /* pop sigmask */ - .cfi_adjust_cfa_offset -4 - jmp *%edx -#elif defined(__FreeBSD__) - pushl %eax - pushl %edx - pushl $0 - pushl %ecx - pushl $SIG_SETMASK - movl $340,%eax - pushl %eax - int $0x80 - addl $16,%esp - popl %eax - popl %edx - jmp *%edx -#else -#error Port me -#endif - .cfi_endproc - .size _UI_siglongjmp_cont, .-_UI_siglongjmp_cont - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits diff --git a/contrib/libunwind/src/x86/unwind_i.h b/contrib/libunwind/src/x86/unwind_i.h deleted file mode 100644 index d2aed609e57..00000000000 --- a/contrib/libunwind/src/x86/unwind_i.h +++ /dev/null @@ -1,66 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include - -#include - -#include "libunwind_i.h" - -/* DWARF column numbers: */ -#define EAX 0 -#define ECX 1 -#define EDX 2 -#define EBX 3 -#define ESP 4 -#define EBP 5 -#define ESI 6 -#define EDI 7 -#define EIP 8 -#define EFLAGS 9 -#define TRAPNO 10 -#define ST0 11 - -#define x86_lock UNW_OBJ(lock) -#define x86_local_resume UNW_OBJ(local_resume) -#define x86_local_addr_space_init UNW_OBJ(local_addr_space_init) -#define x86_scratch_loc UNW_OBJ(scratch_loc) -#define x86_get_scratch_loc UNW_OBJ(get_scratch_loc) -#define x86_r_uc_addr UNW_OBJ(r_uc_addr) -#define x86_sigreturn UNW_OBJ(sigreturn) - -extern void x86_local_addr_space_init (void); -extern int x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, - void *arg); -extern dwarf_loc_t x86_scratch_loc (struct cursor *c, unw_regnum_t reg); -extern dwarf_loc_t x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg); -extern void *x86_r_uc_addr (ucontext_t *uc, int reg); - -extern void x86_sigreturn (unw_cursor_t *cursor); - -#endif /* unwind_i_h */ diff --git a/contrib/libunwind/src/x86_64/Gapply_reg_state.c b/contrib/libunwind/src/x86_64/Gapply_reg_state.c deleted file mode 100644 index eec93046f56..00000000000 --- a/contrib/libunwind/src/x86_64/Gapply_reg_state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_apply_reg_state (unw_cursor_t *cursor, - void *reg_states_data) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_apply_reg_state (&c->dwarf, (dwarf_reg_state_t *)reg_states_data); -} diff --git a/contrib/libunwind/src/x86_64/Gcreate_addr_space.c b/contrib/libunwind/src/x86_64/Gcreate_addr_space.c deleted file mode 100644 index 38ee5afb20f..00000000000 --- a/contrib/libunwind/src/x86_64/Gcreate_addr_space.c +++ /dev/null @@ -1,61 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -#if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN) -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#endif - -PROTECTED unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* - * x86_64 supports only little-endian. - */ - if (byte_order != 0 && byte_order != __LITTLE_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - return as; -#endif -} diff --git a/contrib/libunwind/src/x86_64/Gget_proc_info.c b/contrib/libunwind/src/x86_64/Gget_proc_info.c deleted file mode 100644 index 8def62d2a60..00000000000 --- a/contrib/libunwind/src/x86_64/Gget_proc_info.c +++ /dev/null @@ -1,48 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) -{ - struct cursor *c = (struct cursor *) cursor; - - if (dwarf_make_proc_info (&c->dwarf) < 0) - { - /* On x86-64, some key routines such as _start() and _dl_start() - are missing DWARF unwind info. We don't want to fail in that - case, because those frames are uninteresting and just mark - the end of the frame-chain anyhow. */ - memset (pi, 0, sizeof (*pi)); - pi->start_ip = c->dwarf.ip; - pi->end_ip = c->dwarf.ip + 1; - return 0; - } - *pi = c->dwarf.pi; - return 0; -} diff --git a/contrib/libunwind/src/x86_64/Gget_save_loc.c b/contrib/libunwind/src/x86_64/Gget_save_loc.c deleted file mode 100644 index b48fa91848d..00000000000 --- a/contrib/libunwind/src/x86_64/Gget_save_loc.c +++ /dev/null @@ -1,73 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) -{ - struct cursor *c = (struct cursor *) cursor; - dwarf_loc_t loc; - - loc = DWARF_NULL_LOC; /* default to "not saved" */ - - switch (reg) - { - case UNW_X86_64_RBX: loc = c->dwarf.loc[RBX]; break; - case UNW_X86_64_RSP: loc = c->dwarf.loc[RSP]; break; - case UNW_X86_64_RBP: loc = c->dwarf.loc[RBP]; break; - case UNW_X86_64_R12: loc = c->dwarf.loc[R12]; break; - case UNW_X86_64_R13: loc = c->dwarf.loc[R13]; break; - case UNW_X86_64_R14: loc = c->dwarf.loc[R14]; break; - case UNW_X86_64_R15: loc = c->dwarf.loc[R15]; break; - - default: - break; - } - - memset (sloc, 0, sizeof (*sloc)); - - if (DWARF_IS_NULL_LOC (loc)) - { - sloc->type = UNW_SLT_NONE; - return 0; - } - -#if !defined(UNW_LOCAL_ONLY) - if (DWARF_IS_REG_LOC (loc)) - { - sloc->type = UNW_SLT_REG; - sloc->u.regnum = DWARF_GET_LOC (loc); - } - else -#endif - { - sloc->type = UNW_SLT_MEMORY; - sloc->u.addr = DWARF_GET_LOC (loc); - } - return 0; -} diff --git a/contrib/libunwind/src/x86_64/Gglobal.c b/contrib/libunwind/src/x86_64/Gglobal.c deleted file mode 100644 index 8d1fbb4b0a9..00000000000 --- a/contrib/libunwind/src/x86_64/Gglobal.c +++ /dev/null @@ -1,102 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "config.h" -#include "unwind_i.h" -#include "dwarf_i.h" - -HIDDEN define_lock (x86_64_lock); -HIDDEN int tdep_init_done; - -/* See comments for svr4_dbx_register_map[] in gcc/config/i386/i386.c. */ - -HIDDEN const uint8_t dwarf_to_unw_regnum_map[DWARF_NUM_PRESERVED_REGS] = - { - UNW_X86_64_RAX, - UNW_X86_64_RDX, - UNW_X86_64_RCX, - UNW_X86_64_RBX, - UNW_X86_64_RSI, - UNW_X86_64_RDI, - UNW_X86_64_RBP, - UNW_X86_64_RSP, - UNW_X86_64_R8, - UNW_X86_64_R9, - UNW_X86_64_R10, - UNW_X86_64_R11, - UNW_X86_64_R12, - UNW_X86_64_R13, - UNW_X86_64_R14, - UNW_X86_64_R15, - UNW_X86_64_RIP, -#ifdef CONFIG_MSABI_SUPPORT - UNW_X86_64_XMM0, - UNW_X86_64_XMM1, - UNW_X86_64_XMM2, - UNW_X86_64_XMM3, - UNW_X86_64_XMM4, - UNW_X86_64_XMM5, - UNW_X86_64_XMM6, - UNW_X86_64_XMM7, - UNW_X86_64_XMM8, - UNW_X86_64_XMM9, - UNW_X86_64_XMM10, - UNW_X86_64_XMM11, - UNW_X86_64_XMM12, - UNW_X86_64_XMM13, - UNW_X86_64_XMM14, - UNW_X86_64_XMM15 -#endif - }; - -HIDDEN void -tdep_init (void) -{ - intrmask_t saved_mask; - - sigfillset (&unwi_full_mask); - - lock_acquire (&x86_64_lock, saved_mask); - { - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - mi_init (); - - dwarf_init (); - - tdep_init_mem_validate (); - -#ifndef UNW_REMOTE_ONLY - x86_64_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - } - out: - lock_release (&x86_64_lock, saved_mask); -} diff --git a/contrib/libunwind/src/x86_64/Ginit.c b/contrib/libunwind/src/x86_64/Ginit.c deleted file mode 100644 index c66d59ba685..00000000000 --- a/contrib/libunwind/src/x86_64/Ginit.c +++ /dev/null @@ -1,340 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002 Hewlett-Packard Co - Copyright (C) 2007 David Mosberger-Tang - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -PROTECTED unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - -/* XXX fix me: there is currently no way to locate the dyn-info list - by a remote unwinder. On ia64, this is done via a special - unwind-table entry. Perhaps something similar can be done with - DWARF2 unwind info. */ - -static void -put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ - *dyn_info_list_addr = (unw_word_t) &_U_dyn_info_list; - return 0; -} - -#define PAGE_SIZE 4096 -#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1)) - -static int mem_validate_pipe[2] = {-1, -1}; - -static inline void -open_pipe (void) -{ - /* ignore errors for closing invalid fd's */ - close (mem_validate_pipe[0]); - close (mem_validate_pipe[1]); - - pipe2 (mem_validate_pipe, O_CLOEXEC | O_NONBLOCK); -} - -ALWAYS_INLINE -static int -write_validate (void *addr) -{ - int ret = -1; - ssize_t bytes = 0; - - do - { - char buf; - bytes = read (mem_validate_pipe[0], &buf, 1); - } - while ( errno == EINTR ); - - int valid_read = (bytes > 0 || errno == EAGAIN || errno == EWOULDBLOCK); - if (!valid_read) - { - // re-open closed pipe - open_pipe (); - } - - do - { - ret = write (mem_validate_pipe[1], addr, 1); - } - while ( errno == EINTR ); - - return ret; -} - -static int (*mem_validate_func) (void *addr, size_t len); -static int msync_validate (void *addr, size_t len) -{ - if (msync (addr, len, MS_ASYNC) != 0) - { - return -1; - } - - return write_validate (addr); -} - -#ifdef HAVE_MINCORE -static int mincore_validate (void *addr, size_t len) -{ - unsigned char mvec[2]; /* Unaligned access may cross page boundary */ - size_t i; - - /* mincore could fail with EAGAIN but we conservatively return -1 - instead of looping. */ - if (mincore (addr, len, mvec) != 0) - { - return -1; - } - - for (i = 0; i < (len + PAGE_SIZE - 1) / PAGE_SIZE; i++) - { - if (!(mvec[i] & 1)) return -1; - } - - return write_validate (addr); -} -#endif - -/* Initialise memory validation method. On linux kernels <2.6.21, - mincore() returns incorrect value for MAP_PRIVATE mappings, - such as stacks. If mincore() was available at compile time, - check if we can actually use it. If not, use msync() instead. */ -HIDDEN void -tdep_init_mem_validate (void) -{ - open_pipe (); - -#ifdef HAVE_MINCORE - unsigned char present = 1; - unw_word_t addr = PAGE_START((unw_word_t)&present); - unsigned char mvec[1]; - int ret; - while ((ret = mincore ((void*)addr, PAGE_SIZE, mvec)) == -1 && - errno == EAGAIN) {} - if (ret == 0 && (mvec[0] & 1)) - { - Debug(1, "using mincore to validate memory\n"); - mem_validate_func = mincore_validate; - } - else -#endif - { - Debug(1, "using msync to validate memory\n"); - mem_validate_func = msync_validate; - } -} - -/* Cache of already validated addresses */ -#define NLGA 4 -static unw_word_t last_good_addr[NLGA]; -static int lga_victim; - -static int -validate_mem (unw_word_t addr) -{ - int i, victim; - size_t len; - - if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr)) - len = PAGE_SIZE; - else - len = PAGE_SIZE * 2; - - addr = PAGE_START(addr); - - if (addr == 0) - return -1; - - for (i = 0; i < NLGA; i++) - { - if (last_good_addr[i] && (addr == last_good_addr[i])) - return 0; - } - - if (mem_validate_func ((void *) addr, len) == -1) - return -1; - - victim = lga_victim; - for (i = 0; i < NLGA; i++) { - if (!last_good_addr[victim]) { - last_good_addr[victim++] = addr; - return 0; - } - victim = (victim + 1) % NLGA; - } - - /* All slots full. Evict the victim. */ - last_good_addr[victim] = addr; - victim = (victim + 1) % NLGA; - lga_victim = victim; - - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - if (unlikely (write)) - { - Debug (16, "mem[%016lx] <- %lx\n", addr, *val); - *(unw_word_t *) addr = *val; - } - else - { - /* validate address */ - const struct cursor *c = (const struct cursor *)arg; - if (likely (c != NULL) && unlikely (c->validate) - && unlikely (validate_mem (addr))) { - Debug (16, "mem[%016lx] -> invalid\n", addr); - return -1; - } - *val = *(unw_word_t *) addr; - Debug (16, "mem[%016lx] -> %lx\n", addr, *val); - } - return 0; -} - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, - void *arg) -{ - unw_word_t *addr; - ucontext_t *uc = ((struct cursor *)arg)->uc; - - if (unw_is_fpreg (reg)) - goto badreg; - - if (!(addr = x86_64_r_uc_addr (uc, reg))) - goto badreg; - - if (write) - { - *(unw_word_t *) addr = *val; - Debug (12, "%s <- 0x%016lx\n", unw_regname (reg), *val); - } - else - { - *val = *(unw_word_t *) addr; - Debug (12, "%s -> 0x%016lx\n", unw_regname (reg), *val); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - ucontext_t *uc = ((struct cursor *)arg)->uc; - unw_fpreg_t *addr; - - if (!unw_is_fpreg (reg)) - goto badreg; - - if (!(addr = x86_64_r_uc_addr (uc, reg))) - goto badreg; - - if (write) - { - Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - *(unw_fpreg_t *) addr = *val; - } - else - { - *val = *(unw_fpreg_t *) addr; - Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - /* attempt to access a non-preserved register */ - return -UNW_EBADREG; -} - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - return _Uelf64_get_proc_name (as, getpid (), ip, buf, buf_len, offp); -} - -HIDDEN void -x86_64_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.caching_policy = UNWI_DEFAULT_CACHING_POLICY; - local_addr_space.acc.find_proc_info = dwarf_find_proc_info; - local_addr_space.acc.put_unwind_info = put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = x86_64_local_resume; - local_addr_space.acc.get_proc_name = get_static_proc_name; - unw_flush_cache (&local_addr_space, 0, 0); - - memset (last_good_addr, 0, sizeof (unw_word_t) * NLGA); - lga_victim = 0; -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/x86_64/Ginit_local.c b/contrib/libunwind/src/x86_64/Ginit_local.c deleted file mode 100644 index 7696f11caf9..00000000000 --- a/contrib/libunwind/src/x86_64/Ginit_local.c +++ /dev/null @@ -1,81 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "init.h" - -#ifdef UNW_REMOTE_ONLY - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - return -UNW_EINVAL; -} - -#else /* !UNW_REMOTE_ONLY */ - -static int -unw_init_local_common (unw_cursor_t *cursor, ucontext_t *uc, unsigned use_prev_instr) -{ - struct cursor *c = (struct cursor *) cursor; - - if (unlikely (!tdep_init_done)) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = unw_local_addr_space; - c->dwarf.as_arg = c; - c->uc = uc; - c->validate = 0; - return common_init (c, use_prev_instr); -} - -PROTECTED int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - return unw_init_local_common(cursor, uc, 1); -} - -PROTECTED int -unw_init_local2 (unw_cursor_t *cursor, ucontext_t *uc, int flag) -{ - if (!flag) - { - return unw_init_local_common(cursor, uc, 1); - } - else if (flag == UNW_INIT_SIGNAL_FRAME) - { - return unw_init_local_common(cursor, uc, 0); - } - else - { - return -UNW_EINVAL; - } -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/contrib/libunwind/src/x86_64/Ginit_remote.c b/contrib/libunwind/src/x86_64/Ginit_remote.c deleted file mode 100644 index f3b7bb97c9c..00000000000 --- a/contrib/libunwind/src/x86_64/Ginit_remote.c +++ /dev/null @@ -1,57 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "init.h" -#include "unwind_i.h" - -PROTECTED int -unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) -{ -#ifdef UNW_LOCAL_ONLY - return -UNW_EINVAL; -#else /* !UNW_LOCAL_ONLY */ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = as; - if (as == unw_local_addr_space) - { - c->dwarf.as_arg = c; - c->uc = as_arg; - } - else - { - c->dwarf.as_arg = as_arg; - c->uc = NULL; - } - return common_init (c, 0); -#endif /* !UNW_LOCAL_ONLY */ -} diff --git a/contrib/libunwind/src/x86_64/Gos-freebsd.c b/contrib/libunwind/src/x86_64/Gos-freebsd.c deleted file mode 100644 index 8701aefb9f8..00000000000 --- a/contrib/libunwind/src/x86_64/Gos-freebsd.c +++ /dev/null @@ -1,218 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2010 Konstantin Belousov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include "unwind_i.h" -#include "ucontext_i.h" - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ - /* XXXKIB */ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, w1, w2, b0, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - /* Check if RIP points at sigreturn sequence. -48 8d 7c 24 10 lea SIGF_UC(%rsp),%rdi -6a 00 pushq $0 -48 c7 c0 a1 01 00 00 movq $SYS_sigreturn,%rax -0f 05 syscall -f4 0: hlt -eb fd jmp 0b - */ - - ip = c->dwarf.ip; - c->sigcontext_format = X86_64_SCF_NONE; - if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 - || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0 - || (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0) - return 0; - w2 &= 0xffffff; - if (w0 == 0x48006a10247c8d48 && - w1 == 0x050f000001a1c0c7 && - w2 == 0x0000000000fdebf4) - { - c->sigcontext_format = X86_64_SCF_FREEBSD_SIGFRAME; - return (c->sigcontext_format); - } - /* Check if RIP points at standard syscall sequence. -49 89 ca mov %rcx,%r10 -0f 05 syscall - */ - if ((ret = (*a->access_mem) (as, ip - 5, &b0, 0, arg)) < 0) - return (0); - Debug (12, "b0 0x%lx\n", b0); - if ((b0 & 0xffffffffffffff) == 0x050fca89490000 || - (b0 & 0xffffffffff) == 0x050fca8949) - { - c->sigcontext_format = X86_64_SCF_FREEBSD_SYSCALL; - return (c->sigcontext_format); - } - return (X86_64_SCF_NONE); -} - -PROTECTED int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t ucontext; - int ret; - - if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME) - { - ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); - c->sigcontext_addr = c->dwarf.cfa; - Debug(1, "signal frame, skip over trampoline\n"); - - struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); - ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - - c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); - c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); - c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); - c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0); - c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0); - c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0); - c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); - c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); - c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); - c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); - c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); - c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); - c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); - c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); - c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); - c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); - c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); - - return 0; - } - else if (c->sigcontext_format == X86_64_SCF_FREEBSD_SYSCALL) - { - c->dwarf.loc[RCX] = c->dwarf.loc[R10]; - /* rsp_loc = DWARF_LOC(c->dwarf.cfa - 8, 0); */ - /* rbp_loc = c->dwarf.loc[RBP]; */ - c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); - ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); - Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", - (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]), - (unsigned long long) c->dwarf.ip); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - c->dwarf.cfa += 8; - c->dwarf.use_prev_instr = 1; - return 1; - } - else - return -UNW_EBADFRAME; - -} - -#ifndef UNW_REMOTE_ONLY -HIDDEN void * -x86_64_r_uc_addr (ucontext_t *uc, int reg) -{ - /* NOTE: common_init() in init.h inlines these for fast path access. */ - void *addr; - - switch (reg) - { - case UNW_X86_64_R8: addr = &uc->uc_mcontext.mc_r8; break; - case UNW_X86_64_R9: addr = &uc->uc_mcontext.mc_r9; break; - case UNW_X86_64_R10: addr = &uc->uc_mcontext.mc_r10; break; - case UNW_X86_64_R11: addr = &uc->uc_mcontext.mc_r11; break; - case UNW_X86_64_R12: addr = &uc->uc_mcontext.mc_r12; break; - case UNW_X86_64_R13: addr = &uc->uc_mcontext.mc_r13; break; - case UNW_X86_64_R14: addr = &uc->uc_mcontext.mc_r14; break; - case UNW_X86_64_R15: addr = &uc->uc_mcontext.mc_r15; break; - case UNW_X86_64_RDI: addr = &uc->uc_mcontext.mc_rdi; break; - case UNW_X86_64_RSI: addr = &uc->uc_mcontext.mc_rsi; break; - case UNW_X86_64_RBP: addr = &uc->uc_mcontext.mc_rbp; break; - case UNW_X86_64_RBX: addr = &uc->uc_mcontext.mc_rbx; break; - case UNW_X86_64_RDX: addr = &uc->uc_mcontext.mc_rdx; break; - case UNW_X86_64_RAX: addr = &uc->uc_mcontext.mc_rax; break; - case UNW_X86_64_RCX: addr = &uc->uc_mcontext.mc_rcx; break; - case UNW_X86_64_RSP: addr = &uc->uc_mcontext.mc_rsp; break; - case UNW_X86_64_RIP: addr = &uc->uc_mcontext.mc_rip; break; - - default: - addr = NULL; - } - return addr; -} - -HIDDEN NORETURN void -x86_64_sigreturn (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - ucontext_t *uc = (ucontext_t *)(c->sigcontext_addr + - offsetof(struct sigframe, sf_uc)); - - uc->uc_mcontext.mc_r8 = c->uc->uc_mcontext.mc_r8; - uc->uc_mcontext.mc_r9 = c->uc->uc_mcontext.mc_r9; - uc->uc_mcontext.mc_r10 = c->uc->uc_mcontext.mc_r10; - uc->uc_mcontext.mc_r11 = c->uc->uc_mcontext.mc_r11; - uc->uc_mcontext.mc_r12 = c->uc->uc_mcontext.mc_r12; - uc->uc_mcontext.mc_r13 = c->uc->uc_mcontext.mc_r13; - uc->uc_mcontext.mc_r14 = c->uc->uc_mcontext.mc_r14; - uc->uc_mcontext.mc_r15 = c->uc->uc_mcontext.mc_r15; - uc->uc_mcontext.mc_rdi = c->uc->uc_mcontext.mc_rdi; - uc->uc_mcontext.mc_rsi = c->uc->uc_mcontext.mc_rsi; - uc->uc_mcontext.mc_rbp = c->uc->uc_mcontext.mc_rbp; - uc->uc_mcontext.mc_rbx = c->uc->uc_mcontext.mc_rbx; - uc->uc_mcontext.mc_rdx = c->uc->uc_mcontext.mc_rdx; - uc->uc_mcontext.mc_rax = c->uc->uc_mcontext.mc_rax; - uc->uc_mcontext.mc_rcx = c->uc->uc_mcontext.mc_rcx; - uc->uc_mcontext.mc_rsp = c->uc->uc_mcontext.mc_rsp; - uc->uc_mcontext.mc_rip = c->uc->uc_mcontext.mc_rip; - - Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", - (unsigned long long) c->dwarf.ip, uc); - sigreturn(uc); - abort(); -} -#endif diff --git a/contrib/libunwind/src/x86_64/Gos-linux.c b/contrib/libunwind/src/x86_64/Gos-linux.c deleted file mode 100644 index 0a3c21221fb..00000000000 --- a/contrib/libunwind/src/x86_64/Gos-linux.c +++ /dev/null @@ -1,156 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "ucontext_i.h" - -#include - -HIDDEN void -tdep_fetch_frame (struct dwarf_cursor *dw, unw_word_t ip, int need_unwind_info) -{ - struct cursor *c = (struct cursor *) dw; - assert(! need_unwind_info || dw->pi_valid); - assert(! need_unwind_info || dw->pi.unwind_info); - if (dw->pi_valid - && dw->pi.unwind_info - && ((struct dwarf_cie_info *) dw->pi.unwind_info)->signal_frame) - c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; - else - c->sigcontext_format = X86_64_SCF_NONE; - - Debug(5, "fetch frame ip=0x%lx cfa=0x%lx format=%d\n", - dw->ip, dw->cfa, c->sigcontext_format); -} - -HIDDEN int -tdep_cache_frame (struct dwarf_cursor *dw) -{ - struct cursor *c = (struct cursor *) dw; - - Debug(5, "cache frame ip=0x%lx cfa=0x%lx format=%d\n", - dw->ip, dw->cfa, c->sigcontext_format); - return c->sigcontext_format; -} - -HIDDEN void -tdep_reuse_frame (struct dwarf_cursor *dw, int frame) -{ - struct cursor *c = (struct cursor *) dw; - c->sigcontext_format = frame; - if (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME) - { - c->frame_info.frame_type = UNW_X86_64_FRAME_SIGRETURN; - /* Offset from cfa to ucontext_t in signal frame. */ - c->frame_info.cfa_reg_offset = 0; - c->sigcontext_addr = dw->cfa; - } - - Debug(5, "reuse frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx offset=%+d\n", - dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr, - (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME - ? c->frame_info.cfa_reg_offset : 0)); -} - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - return c->sigcontext_format != X86_64_SCF_NONE; -} - -PROTECTED int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ -#if UNW_DEBUG /* To silence compiler warnings */ - /* Should not get here because we now use kernel-provided dwarf - information for the signal trampoline and dwarf_step() works. - Hence unw_step() should never call this function. Maybe - restore old non-dwarf signal handling here, but then the - gating on unw_is_signal_frame() needs to be removed. */ - struct cursor *c = (struct cursor *) cursor; - Debug(1, "old format signal frame? format=%d addr=0x%lx cfa=0x%lx\n", - c->sigcontext_format, c->sigcontext_addr, c->dwarf.cfa); -#endif - return -UNW_EBADFRAME; -} - -#ifndef UNW_REMOTE_ONLY -HIDDEN void * -x86_64_r_uc_addr (ucontext_t *uc, int reg) -{ - /* NOTE: common_init() in init.h inlines these for fast path access. */ - void *addr; - - switch (reg) - { - case UNW_X86_64_R8: addr = &uc->uc_mcontext.gregs[REG_R8]; break; - case UNW_X86_64_R9: addr = &uc->uc_mcontext.gregs[REG_R9]; break; - case UNW_X86_64_R10: addr = &uc->uc_mcontext.gregs[REG_R10]; break; - case UNW_X86_64_R11: addr = &uc->uc_mcontext.gregs[REG_R11]; break; - case UNW_X86_64_R12: addr = &uc->uc_mcontext.gregs[REG_R12]; break; - case UNW_X86_64_R13: addr = &uc->uc_mcontext.gregs[REG_R13]; break; - case UNW_X86_64_R14: addr = &uc->uc_mcontext.gregs[REG_R14]; break; - case UNW_X86_64_R15: addr = &uc->uc_mcontext.gregs[REG_R15]; break; - case UNW_X86_64_RDI: addr = &uc->uc_mcontext.gregs[REG_RDI]; break; - case UNW_X86_64_RSI: addr = &uc->uc_mcontext.gregs[REG_RSI]; break; - case UNW_X86_64_RBP: addr = &uc->uc_mcontext.gregs[REG_RBP]; break; - case UNW_X86_64_RBX: addr = &uc->uc_mcontext.gregs[REG_RBX]; break; - case UNW_X86_64_RDX: addr = &uc->uc_mcontext.gregs[REG_RDX]; break; - case UNW_X86_64_RAX: addr = &uc->uc_mcontext.gregs[REG_RAX]; break; - case UNW_X86_64_RCX: addr = &uc->uc_mcontext.gregs[REG_RCX]; break; - case UNW_X86_64_RSP: addr = &uc->uc_mcontext.gregs[REG_RSP]; break; - case UNW_X86_64_RIP: addr = &uc->uc_mcontext.gregs[REG_RIP]; break; - - default: - addr = NULL; - } - return addr; -} - -/* sigreturn() is a no-op on x86_64 glibc. */ -HIDDEN NORETURN void -x86_64_sigreturn (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - mcontext_t *sc_mcontext = &((ucontext_t*)sc)->uc_mcontext; - /* Copy in saved uc - all preserved regs are at the start of sigcontext */ - memcpy(sc_mcontext, &c->uc->uc_mcontext, - DWARF_NUM_PRESERVED_REGS * sizeof(unw_word_t)); - - Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", - (unsigned long long) c->dwarf.ip, sc); - __asm__ __volatile__ ("mov %0, %%rsp;" - "mov %1, %%rax;" - "syscall" - :: "r"(sc), "i"(SYS_rt_sigreturn) - : "memory"); - abort(); -} - -#endif diff --git a/contrib/libunwind/src/x86_64/Greg_states_iterate.c b/contrib/libunwind/src/x86_64/Greg_states_iterate.c deleted file mode 100644 index a39837a1781..00000000000 --- a/contrib/libunwind/src/x86_64/Greg_states_iterate.c +++ /dev/null @@ -1,37 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2003 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_reg_states_iterate (unw_cursor_t *cursor, - unw_reg_states_callback cb, void *token) -{ - struct cursor *c = (struct cursor *) cursor; - - return dwarf_reg_states_iterate (&c->dwarf, cb, token); -} diff --git a/contrib/libunwind/src/x86_64/Gregs.c b/contrib/libunwind/src/x86_64/Gregs.c deleted file mode 100644 index baf8a24f0b9..00000000000 --- a/contrib/libunwind/src/x86_64/Gregs.c +++ /dev/null @@ -1,138 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -#if 0 -static inline dwarf_loc_t -linux_scratch_loc (struct cursor *c, unw_regnum_t reg) -{ - unw_word_t addr = c->sigcontext_addr; - - switch (c->sigcontext_format) - { - case X86_64_SCF_NONE: - return DWARF_REG_LOC (&c->dwarf, reg); - - case X86_64_SCF_LINUX_RT_SIGFRAME: - addr += LINUX_UC_MCONTEXT_OFF; - break; - - case X86_64_SCF_FREEBSD_SIGFRAME: - addr += FREEBSD_UC_MCONTEXT_OFF; - break; - } - - return DWARF_REG_LOC (&c->dwarf, reg); - -} - -HIDDEN dwarf_loc_t -x86_64_scratch_loc (struct cursor *c, unw_regnum_t reg) -{ - if (c->sigcontext_addr) - return linux_scratch_loc (c, reg); - else - return DWARF_REG_LOC (&c->dwarf, reg); -} -#endif - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - dwarf_loc_t loc = DWARF_NULL_LOC; - unsigned int mask; - int arg_num; - - switch (reg) - { - - case UNW_X86_64_RIP: - if (write) - c->dwarf.ip = *valp; /* also update the RIP cache */ - loc = c->dwarf.loc[RIP]; - break; - - case UNW_X86_64_CFA: - case UNW_X86_64_RSP: - if (write) - return -UNW_EREADONLYREG; - *valp = c->dwarf.cfa; - return 0; - - case UNW_X86_64_RAX: - case UNW_X86_64_RDX: - arg_num = reg - UNW_X86_64_RAX; - mask = (1 << arg_num); - if (write) - { - c->dwarf.eh_args[arg_num] = *valp; - c->dwarf.eh_valid_mask |= mask; - return 0; - } - else if ((c->dwarf.eh_valid_mask & mask) != 0) - { - *valp = c->dwarf.eh_args[arg_num]; - return 0; - } - else - loc = c->dwarf.loc[(reg == UNW_X86_64_RAX) ? RAX : RDX]; - break; - - case UNW_X86_64_RCX: loc = c->dwarf.loc[RCX]; break; - case UNW_X86_64_RBX: loc = c->dwarf.loc[RBX]; break; - - case UNW_X86_64_RBP: loc = c->dwarf.loc[RBP]; break; - case UNW_X86_64_RSI: loc = c->dwarf.loc[RSI]; break; - case UNW_X86_64_RDI: loc = c->dwarf.loc[RDI]; break; - case UNW_X86_64_R8: loc = c->dwarf.loc[R8]; break; - case UNW_X86_64_R9: loc = c->dwarf.loc[R9]; break; - case UNW_X86_64_R10: loc = c->dwarf.loc[R10]; break; - case UNW_X86_64_R11: loc = c->dwarf.loc[R11]; break; - case UNW_X86_64_R12: loc = c->dwarf.loc[R12]; break; - case UNW_X86_64_R13: loc = c->dwarf.loc[R13]; break; - case UNW_X86_64_R14: loc = c->dwarf.loc[R14]; break; - case UNW_X86_64_R15: loc = c->dwarf.loc[R15]; break; - - default: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; - } - - if (write) - return dwarf_put (&c->dwarf, loc, *valp); - else - return dwarf_get (&c->dwarf, loc, valp); -} - -HIDDEN int -tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, - int write) -{ - return -UNW_EBADREG; -} diff --git a/contrib/libunwind/src/x86_64/Gresume.c b/contrib/libunwind/src/x86_64/Gresume.c deleted file mode 100644 index 3d40756e481..00000000000 --- a/contrib/libunwind/src/x86_64/Gresume.c +++ /dev/null @@ -1,123 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2002-2004 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "offsets.h" -#include "unwind_i.h" - -#ifndef UNW_REMOTE_ONLY - -HIDDEN inline int -x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ - struct cursor *c = (struct cursor *) cursor; - ucontext_t *uc = c->uc; - - /* Ensure c->pi is up-to-date. On x86-64, it's relatively common to - be missing DWARF unwind info. We don't want to fail in that - case, because the frame-chain still would let us do a backtrace - at least. */ - dwarf_make_proc_info (&c->dwarf); - - if (unlikely (c->sigcontext_addr != X86_64_SCF_NONE)) - { - x86_64_sigreturn(cursor); - abort(); - } - else - { - Debug (8, "resuming at ip=%llx via setcontext()\n", - (unsigned long long) c->dwarf.ip); - setcontext (uc); - } - return -UNW_EINVAL; -} - -#endif /* !UNW_REMOTE_ONLY */ - -/* This routine is responsible for copying the register values in - cursor C and establishing them as the current machine state. */ - -static inline int -establish_machine_state (struct cursor *c) -{ - int (*access_reg) (unw_addr_space_t, unw_regnum_t, unw_word_t *, - int write, void *); - int (*access_fpreg) (unw_addr_space_t, unw_regnum_t, unw_fpreg_t *, - int write, void *); - unw_addr_space_t as = c->dwarf.as; - void *arg = c->dwarf.as_arg; - unw_fpreg_t fpval; - unw_word_t val; - int reg; - - access_reg = as->acc.access_reg; - access_fpreg = as->acc.access_fpreg; - - Debug (8, "copying out cursor state\n"); - - for (reg = 0; reg <= UNW_REG_LAST; ++reg) - { - Debug (16, "copying %s %d\n", unw_regname (reg), reg); - if (unw_is_fpreg (reg)) - { - if (tdep_access_fpreg (c, reg, &fpval, 0) >= 0) - (*access_fpreg) (as, reg, &fpval, 1, arg); - } - else - { - if (tdep_access_reg (c, reg, &val, 0) >= 0) - (*access_reg) (as, reg, &val, 1, arg); - } - } - - if (c->dwarf.args_size) - { - if (tdep_access_reg (c, UNW_X86_64_RSP, &val, 0) >= 0) - { - val += c->dwarf.args_size; - (*access_reg) (as, UNW_X86_64_RSP, &val, 1, arg); - } - } - return 0; -} - -PROTECTED int -unw_resume (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - Debug (1, "(cursor=%p)\n", c); - - if ((ret = establish_machine_state (c)) < 0) - return ret; - - return (*c->dwarf.as->acc.resume) (c->dwarf.as, (unw_cursor_t *) c, - c->dwarf.as_arg); -} diff --git a/contrib/libunwind/src/x86_64/Gstash_frame.c b/contrib/libunwind/src/x86_64/Gstash_frame.c deleted file mode 100644 index 2c7bc312e28..00000000000 --- a/contrib/libunwind/src/x86_64/Gstash_frame.c +++ /dev/null @@ -1,119 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "ucontext_i.h" - -HIDDEN void -tdep_stash_frame (struct dwarf_cursor *d, struct dwarf_reg_state *rs) -{ - struct cursor *c = (struct cursor *) dwarf_to_cursor (d); - unw_tdep_frame_t *f = &c->frame_info; - - Debug (4, "ip=0x%lx cfa=0x%lx type %d cfa [where=%d val=%ld] cfaoff=%ld" - " ra=0x%lx rbp [where=%d val=%ld @0x%lx] rsp [where=%d val=%ld @0x%lx]\n", - d->ip, d->cfa, f->frame_type, - rs->reg.where[DWARF_CFA_REG_COLUMN], - rs->reg.val[DWARF_CFA_REG_COLUMN], - rs->reg.val[DWARF_CFA_OFF_COLUMN], - DWARF_GET_LOC(d->loc[rs->ret_addr_column]), - rs->reg.where[RBP], rs->reg.val[RBP], DWARF_GET_LOC(d->loc[RBP]), - rs->reg.where[RSP], rs->reg.val[RSP], DWARF_GET_LOC(d->loc[RSP])); - - if (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_EXPR && - rs->reg.where[RBP] == DWARF_WHERE_EXPR) { - /* Check for GCC generated alignment frame for rsp. A simple - * def_cfa_expr that loads a constant offset from rbp, where the - * addres of the rip was pushed on the stack */ - unw_word_t cfa_addr = rs->reg.val[DWARF_CFA_REG_COLUMN]; - unw_word_t rbp_addr = rs->reg.val[RBP]; - unw_word_t cfa_offset; - - int ret = dwarf_stack_aligned(d, cfa_addr, rbp_addr, &cfa_offset); - if (ret) { - f->frame_type = UNW_X86_64_FRAME_ALIGNED; - f->cfa_reg_offset = cfa_offset; - f->cfa_reg_rsp = 0; - } - } - - /* A standard frame is defined as: - - CFA is register-relative offset off RBP or RSP; - - Return address is saved at CFA-8; - - RBP is unsaved or saved at CFA+offset, offset != -1; - - RSP is unsaved or saved at CFA+offset, offset != -1. */ - if (f->frame_type == UNW_X86_64_FRAME_OTHER - && (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG) - && (rs->reg.val[DWARF_CFA_REG_COLUMN] == RBP - || rs->reg.val[DWARF_CFA_REG_COLUMN] == RSP) - && labs((long) rs->reg.val[DWARF_CFA_OFF_COLUMN]) < (1 << 28) - && DWARF_GET_LOC(d->loc[rs->ret_addr_column]) == d->cfa-8 - && (rs->reg.where[RBP] == DWARF_WHERE_UNDEF - || rs->reg.where[RBP] == DWARF_WHERE_SAME - || (rs->reg.where[RBP] == DWARF_WHERE_CFAREL - && labs((long) rs->reg.val[RBP]) < (1 << 14) - && rs->reg.val[RBP]+1 != 0)) - && (rs->reg.where[RSP] == DWARF_WHERE_UNDEF - || rs->reg.where[RSP] == DWARF_WHERE_SAME - || (rs->reg.where[RSP] == DWARF_WHERE_CFAREL - && labs((long) rs->reg.val[RSP]) < (1 << 14) - && rs->reg.val[RSP]+1 != 0))) - { - /* Save information for a standard frame. */ - f->frame_type = UNW_X86_64_FRAME_STANDARD; - f->cfa_reg_rsp = (rs->reg.val[DWARF_CFA_REG_COLUMN] == RSP); - f->cfa_reg_offset = rs->reg.val[DWARF_CFA_OFF_COLUMN]; - if (rs->reg.where[RBP] == DWARF_WHERE_CFAREL) - f->rbp_cfa_offset = rs->reg.val[RBP]; - if (rs->reg.where[RSP] == DWARF_WHERE_CFAREL) - f->rsp_cfa_offset = rs->reg.val[RSP]; - Debug (4, " standard frame\n"); - } - - /* Signal frame was detected via augmentation in tdep_fetch_frame() */ - else if (f->frame_type == UNW_X86_64_FRAME_SIGRETURN) - { - /* Later we are going to fish out {RBP,RSP,RIP} from sigcontext via - their ucontext_t offsets. Confirm DWARF info agrees with the - offsets we expect. */ - -#ifndef NDEBUG - const unw_word_t uc = c->sigcontext_addr; - - assert (DWARF_GET_LOC(d->loc[RIP]) - uc == UC_MCONTEXT_GREGS_RIP); - assert (DWARF_GET_LOC(d->loc[RBP]) - uc == UC_MCONTEXT_GREGS_RBP); - assert (DWARF_GET_LOC(d->loc[RSP]) - uc == UC_MCONTEXT_GREGS_RSP); -#endif - - Debug (4, " sigreturn frame\n"); - } - - else if (f->frame_type == UNW_X86_64_FRAME_ALIGNED) { - Debug (4, " aligned frame, offset %li\n", f->cfa_reg_offset); - } - - /* PLT and guessed RBP-walked frames are handled in unw_step(). */ - else - Debug (4, " unusual frame\n"); -} diff --git a/contrib/libunwind/src/x86_64/Gstep.c b/contrib/libunwind/src/x86_64/Gstep.c deleted file mode 100644 index 5af13e0c3a1..00000000000 --- a/contrib/libunwind/src/x86_64/Gstep.c +++ /dev/null @@ -1,227 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include - -/* Recognise PLT entries such as: - 3bdf0: ff 25 e2 49 13 00 jmpq *0x1349e2(%rip) - 3bdf6: 68 ae 03 00 00 pushq $0x3ae - 3bdfb: e9 00 c5 ff ff jmpq 38300 <_init+0x18> */ -static int -is_plt_entry (struct dwarf_cursor *c) -{ - unw_word_t w0, w1; - unw_accessors_t *a; - int ret; - - a = unw_get_accessors (c->as); - if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0 - || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0) - return 0; - - ret = (((w0 & 0xffff) == 0x25ff) - && (((w0 >> 48) & 0xff) == 0x68) - && (((w1 >> 24) & 0xff) == 0xe9)); - - Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret); - return ret; -} - -PROTECTED int -unw_step (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret, i; - -#if CONSERVATIVE_CHECKS - int val = c->validate; - c->validate = 1; -#endif - - Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx)\n", - c, c->dwarf.ip, c->dwarf.cfa); - - /* Try DWARF-based unwinding... */ - c->sigcontext_format = X86_64_SCF_NONE; - ret = dwarf_step (&c->dwarf); - -#if CONSERVATIVE_CHECKS - c->validate = val; -#endif - - if (ret < 0 && ret != -UNW_ENOINFO) - { - Debug (2, "returning %d\n", ret); - return ret; - } - - if (likely (ret >= 0)) - { - /* x86_64 ABI specifies that end of call-chain is marked with a - NULL RBP or undefined return address */ - if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) - { - c->dwarf.ip = 0; - ret = 0; - } - } - else - { - /* DWARF failed. There isn't much of a usable frame-chain on x86-64, - but we do need to handle two special-cases: - - (i) signal trampoline: Old kernels and older libcs don't - export the vDSO needed to get proper unwind info for the - trampoline. Recognize that case by looking at the code - and filling in things by hand. - - (ii) PLT (shared-library) call-stubs: PLT stubs are invoked - via CALLQ. Try this for all non-signal trampoline - code. */ - - unw_word_t prev_ip = c->dwarf.ip, prev_cfa = c->dwarf.cfa; - struct dwarf_loc rbp_loc, rsp_loc, rip_loc; - - /* We could get here because of missing/bad unwind information. - Validate all addresses before dereferencing. */ - c->validate = 1; - - Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); - - if (unw_is_signal_frame (cursor) > 0) - { - ret = unw_handle_signal_frame(cursor); - if (ret < 0) - { - Debug (2, "returning 0\n"); - return 0; - } - } - else if (is_plt_entry (&c->dwarf)) - { - /* Like regular frame, CFA = RSP+8, RA = [CFA-8], no regs saved. */ - Debug (2, "found plt entry\n"); - c->frame_info.cfa_reg_offset = 8; - c->frame_info.cfa_reg_rsp = -1; - c->frame_info.frame_type = UNW_X86_64_FRAME_STANDARD; - c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); - c->dwarf.cfa += 8; - } - else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) - { - for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - } - else - { - unw_word_t rbp; - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp); - if (ret < 0) - { - Debug (2, "returning %d [RBP=0x%lx]\n", ret, - DWARF_GET_LOC (c->dwarf.loc[RBP])); - return ret; - } - - if (!rbp) - { - /* Looks like we may have reached the end of the call-chain. */ - rbp_loc = DWARF_NULL_LOC; - rsp_loc = DWARF_NULL_LOC; - rip_loc = DWARF_NULL_LOC; - } - else - { - unw_word_t rbp1 = 0; - rbp_loc = DWARF_LOC(rbp, 0); - rsp_loc = DWARF_NULL_LOC; - rip_loc = DWARF_LOC (rbp + 8, 0); - ret = dwarf_get (&c->dwarf, rbp_loc, &rbp1); - Debug (1, "[RBP=0x%lx] = 0x%lx (cfa = 0x%lx) -> 0x%lx\n", - (unsigned long) DWARF_GET_LOC (c->dwarf.loc[RBP]), - rbp, c->dwarf.cfa, rbp1); - - /* Heuristic to determine incorrect guess. For RBP to be a - valid frame it needs to be above current CFA, but don't - let it go more than a little. Note that we can't deduce - anything about new RBP (rbp1) since it may not be a frame - pointer in the frame above. Just check we get the value. */ - if (ret < 0 - || rbp < c->dwarf.cfa - || (rbp - c->dwarf.cfa) > 0x4000) - { - rip_loc = DWARF_NULL_LOC; - rbp_loc = DWARF_NULL_LOC; - } - - c->frame_info.frame_type = UNW_X86_64_FRAME_GUESSED; - c->frame_info.cfa_reg_rsp = 0; - c->frame_info.cfa_reg_offset = 16; - c->frame_info.rbp_cfa_offset = -16; - c->dwarf.cfa += 16; - } - - /* Mark all registers unsaved */ - for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - - c->dwarf.loc[RBP] = rbp_loc; - c->dwarf.loc[RSP] = rsp_loc; - c->dwarf.loc[RIP] = rip_loc; - c->dwarf.use_prev_instr = 1; - } - - if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) - { - ret = 0; - Debug (2, "NULL %%rbp loc, returning %d\n", ret); - return ret; - } - if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RIP])) - { - ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); - Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", - (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]), - (unsigned long long) c->dwarf.ip); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - ret = 1; - } - else - c->dwarf.ip = 0; - - if (c->dwarf.ip == prev_ip && c->dwarf.cfa == prev_cfa) - return -UNW_EBADFRAME; - } - Debug (2, "returning %d\n", ret); - return ret; -} diff --git a/contrib/libunwind/src/x86_64/Gtrace.c b/contrib/libunwind/src/x86_64/Gtrace.c deleted file mode 100644 index 741227105e1..00000000000 --- a/contrib/libunwind/src/x86_64/Gtrace.c +++ /dev/null @@ -1,551 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2010, 2011 by FERMI NATIONAL ACCELERATOR LABORATORY - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "ucontext_i.h" -#include -#include - -#pragma weak pthread_once -#pragma weak pthread_key_create -#pragma weak pthread_getspecific -#pragma weak pthread_setspecific - -/* Initial hash table size. Table expands by 2 bits (times four). */ -#define HASH_MIN_BITS 14 - -typedef struct -{ - unw_tdep_frame_t *frames; - size_t log_size; - size_t used; - size_t dtor_count; /* Counts how many times our destructor has already - been called. */ -} unw_trace_cache_t; - -static const unw_tdep_frame_t empty_frame = { 0, UNW_X86_64_FRAME_OTHER, -1, -1, 0, -1, -1 }; -static define_lock (trace_init_lock); -static pthread_once_t trace_cache_once = PTHREAD_ONCE_INIT; -static sig_atomic_t trace_cache_once_happen; -static pthread_key_t trace_cache_key; -static struct mempool trace_cache_pool; -static __thread unw_trace_cache_t *tls_cache; -static __thread int tls_cache_destroyed; - -/* Free memory for a thread's trace cache. */ -static void -trace_cache_free (void *arg) -{ - unw_trace_cache_t *cache = arg; - if (++cache->dtor_count < PTHREAD_DESTRUCTOR_ITERATIONS) - { - /* Not yet our turn to get destroyed. Re-install ourselves into the key. */ - pthread_setspecific(trace_cache_key, cache); - Debug(5, "delayed freeing cache %p (%zx to go)\n", cache, - PTHREAD_DESTRUCTOR_ITERATIONS - cache->dtor_count); - return; - } - tls_cache_destroyed = 1; - tls_cache = NULL; - munmap (cache->frames, (1u << cache->log_size) * sizeof(unw_tdep_frame_t)); - mempool_free (&trace_cache_pool, cache); - Debug(5, "freed cache %p\n", cache); -} - -/* Initialise frame tracing for threaded use. */ -static void -trace_cache_init_once (void) -{ - pthread_key_create (&trace_cache_key, &trace_cache_free); - mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); - trace_cache_once_happen = 1; -} - -static unw_tdep_frame_t * -trace_cache_buckets (size_t n) -{ - unw_tdep_frame_t *frames; - size_t i; - - GET_MEMORY(frames, n * sizeof (unw_tdep_frame_t)); - if (likely(frames != NULL)) - for (i = 0; i < n; ++i) - frames[i] = empty_frame; - - return frames; -} - -/* Allocate and initialise hash table for frame cache lookups. - Returns the cache initialised with (1u << HASH_LOW_BITS) hash - buckets, or NULL if there was a memory allocation problem. */ -static unw_trace_cache_t * -trace_cache_create (void) -{ - unw_trace_cache_t *cache; - - if (tls_cache_destroyed) - { - /* The current thread is in the process of exiting. Don't recreate - cache, as we wouldn't have another chance to free it. */ - Debug(5, "refusing to reallocate cache: " - "thread-locals are being deallocated\n"); - return NULL; - } - - if (! (cache = mempool_alloc(&trace_cache_pool))) - { - Debug(5, "failed to allocate cache\n"); - return NULL; - } - - if (! (cache->frames = trace_cache_buckets(1u << HASH_MIN_BITS))) - { - Debug(5, "failed to allocate buckets\n"); - mempool_free(&trace_cache_pool, cache); - return NULL; - } - - cache->log_size = HASH_MIN_BITS; - cache->used = 0; - cache->dtor_count = 0; - tls_cache_destroyed = 0; /* Paranoia: should already be 0. */ - Debug(5, "allocated cache %p\n", cache); - return cache; -} - -/* Expand the hash table in the frame cache if possible. This always - quadruples the hash size, and clears all previous frame entries. */ -static int -trace_cache_expand (unw_trace_cache_t *cache) -{ - size_t old_size = (1u << cache->log_size); - size_t new_log_size = cache->log_size + 2; - unw_tdep_frame_t *new_frames = trace_cache_buckets (1u << new_log_size); - - if (unlikely(! new_frames)) - { - Debug(5, "failed to expand cache to 2^%lu buckets\n", new_log_size); - return -UNW_ENOMEM; - } - - Debug(5, "expanded cache from 2^%lu to 2^%lu buckets\n", cache->log_size, new_log_size); - munmap(cache->frames, old_size * sizeof(unw_tdep_frame_t)); - cache->frames = new_frames; - cache->log_size = new_log_size; - cache->used = 0; - return 0; -} - -static unw_trace_cache_t * -trace_cache_get_unthreaded (void) -{ - unw_trace_cache_t *cache; - intrmask_t saved_mask; - static unw_trace_cache_t *global_cache = NULL; - lock_acquire (&trace_init_lock, saved_mask); - if (! global_cache) - { - mempool_init (&trace_cache_pool, sizeof (unw_trace_cache_t), 0); - global_cache = trace_cache_create (); - } - cache = global_cache; - lock_release (&trace_init_lock, saved_mask); - Debug(5, "using cache %p\n", cache); - return cache; -} - -/* Get the frame cache for the current thread. Create it if there is none. */ -static unw_trace_cache_t * -trace_cache_get (void) -{ - unw_trace_cache_t *cache; - if (likely (pthread_once != NULL)) - { - pthread_once(&trace_cache_once, &trace_cache_init_once); - if (!trace_cache_once_happen) - { - return trace_cache_get_unthreaded(); - } - if (! (cache = tls_cache)) - { - cache = trace_cache_create(); - pthread_setspecific(trace_cache_key, cache); - tls_cache = cache; - } - Debug(5, "using cache %p\n", cache); - return cache; - } - else - { - return trace_cache_get_unthreaded(); - } -} - -/* Initialise frame properties for address cache slot F at address - RIP using current CFA, RBP and RSP values. Modifies CURSOR to - that location, performs one unw_step(), and fills F with what - was discovered about the location. Returns F. - - FIXME: This probably should tell DWARF handling to never evaluate - or use registers other than RBP, RSP and RIP in case there is - highly unusual unwind info which uses these creatively. */ -static unw_tdep_frame_t * -trace_init_addr (unw_tdep_frame_t *f, - unw_cursor_t *cursor, - unw_word_t cfa, - unw_word_t rip, - unw_word_t rbp, - unw_word_t rsp) -{ - struct cursor *c = (struct cursor *) cursor; - struct dwarf_cursor *d = &c->dwarf; - int ret = -UNW_EINVAL; - - /* Initialise frame properties: unknown, not last. */ - f->virtual_address = rip; - f->frame_type = UNW_X86_64_FRAME_OTHER; - f->last_frame = 0; - f->cfa_reg_rsp = -1; - f->cfa_reg_offset = 0; - f->rbp_cfa_offset = -1; - f->rsp_cfa_offset = -1; - - /* Reinitialise cursor to this instruction - but undo next/prev RIP - adjustment because unw_step will redo it - and force RIP, RBP - RSP into register locations (=~ ucontext we keep), then set - their desired values. Then perform the step. */ - d->ip = rip + d->use_prev_instr; - d->cfa = cfa; - d->loc[UNW_X86_64_RIP] = DWARF_REG_LOC (d, UNW_X86_64_RIP); - d->loc[UNW_X86_64_RBP] = DWARF_REG_LOC (d, UNW_X86_64_RBP); - d->loc[UNW_X86_64_RSP] = DWARF_REG_LOC (d, UNW_X86_64_RSP); - c->frame_info = *f; - - if (likely(dwarf_put (d, d->loc[UNW_X86_64_RIP], rip) >= 0) - && likely(dwarf_put (d, d->loc[UNW_X86_64_RBP], rbp) >= 0) - && likely(dwarf_put (d, d->loc[UNW_X86_64_RSP], rsp) >= 0) - && likely((ret = unw_step (cursor)) >= 0)) - *f = c->frame_info; - - /* If unw_step() stopped voluntarily, remember that, even if it - otherwise could not determine anything useful. This avoids - failing trace if we hit frames without unwind info, which is - common for the outermost frame (CRT stuff) on many systems. - This avoids failing trace in very common circumstances; failing - to unw_step() loop wouldn't produce any better result. */ - if (ret == 0) - f->last_frame = -1; - - Debug (3, "frame va %lx type %d last %d cfa %s+%d rbp @ cfa%+d rsp @ cfa%+d\n", - f->virtual_address, f->frame_type, f->last_frame, - f->cfa_reg_rsp ? "rsp" : "rbp", f->cfa_reg_offset, - f->rbp_cfa_offset, f->rsp_cfa_offset); - - return f; -} - -/* Look up and if necessary fill in frame attributes for address RIP - in CACHE using current CFA, RBP and RSP values. Uses CURSOR to - perform any unwind steps necessary to fill the cache. Returns the - frame cache slot which describes RIP. */ -static unw_tdep_frame_t * -trace_lookup (unw_cursor_t *cursor, - unw_trace_cache_t *cache, - unw_word_t cfa, - unw_word_t rip, - unw_word_t rbp, - unw_word_t rsp) -{ - /* First look up for previously cached information using cache as - linear probing hash table with probe step of 1. Majority of - lookups should be completed within few steps, but it is very - important the hash table does not fill up, or performance falls - off the cliff. */ - uint64_t i, addr; - uint64_t cache_size = 1u << cache->log_size; - uint64_t slot = ((rip * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1); - unw_tdep_frame_t *frame; - - for (i = 0; i < 16; ++i) - { - frame = &cache->frames[slot]; - addr = frame->virtual_address; - - /* Return if we found the address. */ - if (likely(addr == rip)) - { - Debug (4, "found address after %ld steps\n", i); - return frame; - } - - /* If slot is empty, reuse it. */ - if (likely(! addr)) - break; - - /* Linear probe to next slot candidate, step = 1. */ - if (++slot >= cache_size) - slot -= cache_size; - } - - /* If we collided after 16 steps, or if the hash is more than half - full, force the hash to expand. Fill the selected slot, whether - it's free or collides. Note that hash expansion drops previous - contents; further lookups will refill the hash. */ - Debug (4, "updating slot %lu after %ld steps, replacing 0x%lx\n", slot, i, addr); - if (unlikely(addr || cache->used >= cache_size / 2)) - { - if (unlikely(trace_cache_expand (cache) < 0)) - return NULL; - - cache_size = 1u << cache->log_size; - slot = ((rip * 0x9e3779b97f4a7c16) >> 43) & (cache_size-1); - frame = &cache->frames[slot]; - addr = frame->virtual_address; - } - - if (! addr) - ++cache->used; - - return trace_init_addr (frame, cursor, cfa, rip, rbp, rsp); -} - -/* Fast stack backtrace for x86-64. - - This is used by backtrace() implementation to accelerate frequent - queries for current stack, without any desire to unwind. It fills - BUFFER with the call tree from CURSOR upwards for at most SIZE - stack levels. The first frame, backtrace itself, is omitted. When - called, SIZE should give the maximum number of entries that can be - stored into BUFFER. Uses an internal thread-specific cache to - accelerate queries. - - The caller should fall back to a unw_step() loop if this function - fails by returning -UNW_ESTOPUNWIND, meaning the routine hit a - stack frame that is too complex to be traced in the fast path. - - This function is tuned for clients which only need to walk the - stack to get the call tree as fast as possible but without any - other details, for example profilers sampling the stack thousands - to millions of times per second. The routine handles the most - common x86-64 ABI stack layouts: CFA is RBP or RSP plus/minus - constant offset, return address is at CFA-8, and RBP and RSP are - either unchanged or saved on stack at constant offset from the CFA; - the signal return frame; and frames without unwind info provided - they are at the outermost (final) frame or can conservatively be - assumed to be frame-pointer based. - - Any other stack layout will cause the routine to give up. There - are only a handful of relatively rarely used functions which do - not have a stack in the standard form: vfork, longjmp, setcontext - and _dl_runtime_profile on common linux systems for example. - - On success BUFFER and *SIZE reflect the trace progress up to *SIZE - stack levels or the outermost frame, which ever is less. It may - stop short of outermost frame if unw_step() loop would also do so, - e.g. if there is no more unwind information; this is not reported - as an error. - - The function returns a negative value for errors, -UNW_ESTOPUNWIND - if tracing stopped because of an unusual frame unwind info. The - BUFFER and *SIZE reflect tracing progress up to the error frame. - - Callers of this function would normally look like this: - - unw_cursor_t cur; - unw_context_t ctx; - void addrs[128]; - int depth = 128; - int ret; - - unw_getcontext(&ctx); - unw_init_local(&cur, &ctx); - if ((ret = unw_tdep_trace(&cur, addrs, &depth)) < 0) - { - depth = 0; - unw_getcontext(&ctx); - unw_init_local(&cur, &ctx); - while ((ret = unw_step(&cur)) > 0 && depth < 128) - { - unw_word_t ip; - unw_get_reg(&cur, UNW_REG_IP, &ip); - addresses[depth++] = (void *) ip; - } - } -*/ -HIDDEN int -tdep_trace (unw_cursor_t *cursor, void **buffer, int *size) -{ - struct cursor *c = (struct cursor *) cursor; - struct dwarf_cursor *d = &c->dwarf; - unw_trace_cache_t *cache; - unw_word_t rbp, rsp, rip, cfa; - int maxdepth = 0; - int depth = 0; - int ret; - - /* Check input parametres. */ - if (unlikely(! cursor || ! buffer || ! size || (maxdepth = *size) <= 0)) - return -UNW_EINVAL; - - Debug (1, "begin ip 0x%lx cfa 0x%lx\n", d->ip, d->cfa); - - /* Tell core dwarf routines to call back to us. */ - d->stash_frames = 1; - - /* Determine initial register values. These are direct access safe - because we know they come from the initial machine context. */ - rip = d->ip; - rsp = cfa = d->cfa; - ACCESS_MEM_FAST(ret, 0, d, DWARF_GET_LOC(d->loc[UNW_X86_64_RBP]), rbp); - assert(ret == 0); - - /* Get frame cache. */ - if (unlikely(! (cache = trace_cache_get()))) - { - Debug (1, "returning %d, cannot get trace cache\n", -UNW_ENOMEM); - *size = 0; - d->stash_frames = 0; - return -UNW_ENOMEM; - } - - /* Trace the stack upwards, starting from current RIP. Adjust - the RIP address for previous/next instruction as the main - unwinding logic would also do. We undo this before calling - back into unw_step(). */ - while (depth < maxdepth) - { - rip -= d->use_prev_instr; - Debug (2, "depth %d cfa 0x%lx rip 0x%lx rsp 0x%lx rbp 0x%lx\n", - depth, cfa, rip, rsp, rbp); - - /* See if we have this address cached. If not, evaluate enough of - the dwarf unwind information to fill the cache line data, or to - decide this frame cannot be handled in fast trace mode. We - cache negative results too to prevent unnecessary dwarf parsing - for common failures. */ - unw_tdep_frame_t *f = trace_lookup (cursor, cache, cfa, rip, rbp, rsp); - - /* If we don't have information for this frame, give up. */ - if (unlikely(! f)) - { - ret = -UNW_ENOINFO; - break; - } - - Debug (3, "frame va %lx type %d last %d cfa %s+%d rbp @ cfa%+d rsp @ cfa%+d\n", - f->virtual_address, f->frame_type, f->last_frame, - f->cfa_reg_rsp ? "rsp" : "rbp", f->cfa_reg_offset, - f->rbp_cfa_offset, f->rsp_cfa_offset); - - assert (f->virtual_address == rip); - - /* Stop if this was the last frame. In particular don't evaluate - new register values as it may not be safe - we don't normally - run with full validation on, and do not want to - and there's - enough bad unwind info floating around that we need to trust - what unw_step() previously said, in potentially bogus frames. */ - if (f->last_frame) - break; - - /* Evaluate CFA and registers for the next frame. */ - switch (f->frame_type) - { - case UNW_X86_64_FRAME_GUESSED: - /* Fall thru to standard processing after forcing validation. */ - c->validate = 1; - - case UNW_X86_64_FRAME_STANDARD: - /* Advance standard traceable frame. */ - cfa = (f->cfa_reg_rsp ? rsp : rbp) + f->cfa_reg_offset; - ACCESS_MEM_FAST(ret, c->validate, d, cfa - 8, rip); - if (likely(ret >= 0) && likely(f->rbp_cfa_offset != -1)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + f->rbp_cfa_offset, rbp); - - /* Don't bother reading RSP from DWARF, CFA becomes new RSP. */ - rsp = cfa; - - /* Next frame needs to back up for unwind info lookup. */ - d->use_prev_instr = 1; - break; - - case UNW_X86_64_FRAME_SIGRETURN: - cfa = cfa + f->cfa_reg_offset; /* cfa now points to ucontext_t. */ - - ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RIP, rip); - if (likely(ret >= 0)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RBP, rbp); - if (likely(ret >= 0)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa + UC_MCONTEXT_GREGS_RSP, rsp); - - /* Resume stack at signal restoration point. The stack is not - necessarily continuous here, especially with sigaltstack(). */ - cfa = rsp; - - /* Next frame should not back up. */ - d->use_prev_instr = 0; - break; - - case UNW_X86_64_FRAME_ALIGNED: - /* Address of RIP was pushed on the stack via a simple - * def_cfa_expr - result stack offset stored in cfa_reg_offset */ - cfa = (f->cfa_reg_rsp ? rsp : rbp) + f->cfa_reg_offset; - ACCESS_MEM_FAST(ret, c->validate, d, cfa, cfa); - if (likely(ret >= 0)) - ACCESS_MEM_FAST(ret, c->validate, d, cfa - 8, rip); - if (likely(ret >= 0)) - ACCESS_MEM_FAST(ret, c->validate, d, rbp, rbp); - - /* Don't bother reading RSP from DWARF, CFA becomes new RSP. */ - rsp = cfa; - - /* Next frame needs to back up for unwind info lookup. */ - d->use_prev_instr = 1; - - break; - - default: - /* We cannot trace through this frame, give up and tell the - caller we had to stop. Data collected so far may still be - useful to the caller, so let it know how far we got. */ - ret = -UNW_ESTOPUNWIND; - break; - } - - Debug (4, "new cfa 0x%lx rip 0x%lx rsp 0x%lx rbp 0x%lx\n", - cfa, rip, rsp, rbp); - - /* If we failed or ended up somewhere bogus, stop. */ - if (unlikely(ret < 0 || rip < 0x4000)) - break; - - /* Record this address in stack trace. We skipped the first address. */ - buffer[depth++] = (void *) (rip - d->use_prev_instr); - } - -#if UNW_DEBUG - Debug (1, "returning %d, depth %d\n", ret, depth); -#endif - *size = depth; - return ret; -} diff --git a/contrib/libunwind/src/x86_64/Lapply_reg_state.c b/contrib/libunwind/src/x86_64/Lapply_reg_state.c deleted file mode 100644 index 7ebada480e5..00000000000 --- a/contrib/libunwind/src/x86_64/Lapply_reg_state.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gapply_reg_state.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Lcreate_addr_space.c b/contrib/libunwind/src/x86_64/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901..00000000000 --- a/contrib/libunwind/src/x86_64/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Lget_proc_info.c b/contrib/libunwind/src/x86_64/Lget_proc_info.c deleted file mode 100644 index 69028b019fc..00000000000 --- a/contrib/libunwind/src/x86_64/Lget_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Lget_save_loc.c b/contrib/libunwind/src/x86_64/Lget_save_loc.c deleted file mode 100644 index 9ea048a9076..00000000000 --- a/contrib/libunwind/src/x86_64/Lget_save_loc.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_save_loc.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Lglobal.c b/contrib/libunwind/src/x86_64/Lglobal.c deleted file mode 100644 index 8c43a67c0ff..00000000000 --- a/contrib/libunwind/src/x86_64/Lglobal.c +++ /dev/null @@ -1,6 +0,0 @@ -#define UNW_LOCAL_ONLY -#include "config.h" -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Linit.c b/contrib/libunwind/src/x86_64/Linit.c deleted file mode 100644 index e9abfdd46a3..00000000000 --- a/contrib/libunwind/src/x86_64/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Linit_local.c b/contrib/libunwind/src/x86_64/Linit_local.c deleted file mode 100644 index 68a1687e854..00000000000 --- a/contrib/libunwind/src/x86_64/Linit_local.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_local.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Linit_remote.c b/contrib/libunwind/src/x86_64/Linit_remote.c deleted file mode 100644 index 58cb04ab7cd..00000000000 --- a/contrib/libunwind/src/x86_64/Linit_remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_remote.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Los-freebsd.c b/contrib/libunwind/src/x86_64/Los-freebsd.c deleted file mode 100644 index a75a205df19..00000000000 --- a/contrib/libunwind/src/x86_64/Los-freebsd.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gos-freebsd.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Los-linux.c b/contrib/libunwind/src/x86_64/Los-linux.c deleted file mode 100644 index 3cc18aabcc3..00000000000 --- a/contrib/libunwind/src/x86_64/Los-linux.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gos-linux.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Lreg_states_iterate.c b/contrib/libunwind/src/x86_64/Lreg_states_iterate.c deleted file mode 100644 index f1eb1e79dcd..00000000000 --- a/contrib/libunwind/src/x86_64/Lreg_states_iterate.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Greg_states_iterate.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Lregs.c b/contrib/libunwind/src/x86_64/Lregs.c deleted file mode 100644 index 2c9c75cd7d9..00000000000 --- a/contrib/libunwind/src/x86_64/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Lresume.c b/contrib/libunwind/src/x86_64/Lresume.c deleted file mode 100644 index 41a8cf003de..00000000000 --- a/contrib/libunwind/src/x86_64/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Lstash_frame.c b/contrib/libunwind/src/x86_64/Lstash_frame.c deleted file mode 100644 index 77587803d08..00000000000 --- a/contrib/libunwind/src/x86_64/Lstash_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstash_frame.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Lstep.c b/contrib/libunwind/src/x86_64/Lstep.c deleted file mode 100644 index c1ac3c7547f..00000000000 --- a/contrib/libunwind/src/x86_64/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/contrib/libunwind/src/x86_64/Ltrace.c b/contrib/libunwind/src/x86_64/Ltrace.c deleted file mode 100644 index fcd3f239c9e..00000000000 --- a/contrib/libunwind/src/x86_64/Ltrace.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gtrace.c" -#endif diff --git a/contrib/libunwind/src/x86_64/getcontext.S b/contrib/libunwind/src/x86_64/getcontext.S deleted file mode 100644 index 7a8b5664bda..00000000000 --- a/contrib/libunwind/src/x86_64/getcontext.S +++ /dev/null @@ -1,134 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 Google, Inc - Contributed by Paul Pluzhnikov - Copyright (C) 2010 Konstantin Belousov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "ucontext_i.h" - -/* int _Ux86_64_getcontext (ucontext_t *ucp) - - Saves the machine context in UCP necessary for libunwind. - Unlike the libc implementation, we don't save the signal mask - and hence avoid the cost of a system call per unwind. - -*/ - - .global _Ux86_64_getcontext - .type _Ux86_64_getcontext, @function -_Ux86_64_getcontext: - .cfi_startproc - - /* Callee saved: RBX, RBP, R12-R15 */ - movq %r12, UC_MCONTEXT_GREGS_R12(%rdi) - movq %r13, UC_MCONTEXT_GREGS_R13(%rdi) - movq %r14, UC_MCONTEXT_GREGS_R14(%rdi) - movq %r15, UC_MCONTEXT_GREGS_R15(%rdi) - movq %rbp, UC_MCONTEXT_GREGS_RBP(%rdi) - movq %rbx, UC_MCONTEXT_GREGS_RBX(%rdi) - - /* Save argument registers (not strictly needed, but setcontext - restores them, so don't restore garbage). */ - movq %r8, UC_MCONTEXT_GREGS_R8(%rdi) - movq %r9, UC_MCONTEXT_GREGS_R9(%rdi) - movq %rdi, UC_MCONTEXT_GREGS_RDI(%rdi) - movq %rsi, UC_MCONTEXT_GREGS_RSI(%rdi) - movq %rdx, UC_MCONTEXT_GREGS_RDX(%rdi) - movq %rax, UC_MCONTEXT_GREGS_RAX(%rdi) - movq %rcx, UC_MCONTEXT_GREGS_RCX(%rdi) - -#if defined __linux__ - /* Save fp state (not needed, except for setcontext not - restoring garbage). */ - leaq UC_MCONTEXT_FPREGS_MEM(%rdi),%r8 - movq %r8, UC_MCONTEXT_FPREGS_PTR(%rdi) - fnstenv (%r8) - stmxcsr FPREGS_OFFSET_MXCSR(%r8) -#elif defined __FreeBSD__ - fxsave UC_MCONTEXT_FPSTATE(%rdi) - movq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi) - movq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi) - /* Save rflags and segment registers, so that sigreturn(2) - does not complain. */ - pushfq - .cfi_adjust_cfa_offset 8 - popq UC_MCONTEXT_RFLAGS(%rdi) - .cfi_adjust_cfa_offset -8 - movl $0, UC_MCONTEXT_FLAGS(%rdi) - movw %cs, UC_MCONTEXT_CS(%rdi) - movw %ss, UC_MCONTEXT_SS(%rdi) -#if 0 - /* Setting the flags to 0 above disables restore of segment - registers from the context */ - movw %ds, UC_MCONTEXT_DS(%rdi) - movw %es, UC_MCONTEXT_ES(%rdi) - movw %fs, UC_MCONTEXT_FS(%rdi) - movw %gs, UC_MCONTEXT_GS(%rdi) -#endif - movq $UC_MCONTEXT_MC_LEN_VAL, UC_MCONTEXT_MC_LEN(%rdi) -#else -#error Port me -#endif - - leaq 8(%rsp), %rax /* exclude this call. */ - movq %rax, UC_MCONTEXT_GREGS_RSP(%rdi) - - movq 0(%rsp), %rax - movq %rax, UC_MCONTEXT_GREGS_RIP(%rdi) - - xorq %rax, %rax - retq - .cfi_endproc - .size _Ux86_64_getcontext, . - _Ux86_64_getcontext - -/* int _Ux86_64_getcontext_trace (ucontext_t *ucp) - - Saves limited machine context in UCP necessary for libunwind. - Unlike _Ux86_64_getcontext, saves only the parts needed for - fast trace. If fast trace fails, caller will have to get the - full context. -*/ - - .global _Ux86_64_getcontext_trace - .hidden _Ux86_64_getcontext_trace - .type _Ux86_64_getcontext_trace, @function -_Ux86_64_getcontext_trace: - .cfi_startproc - - /* Save only RBP, RBX, RSP, RIP - exclude this call. */ - movq %rbp, UC_MCONTEXT_GREGS_RBP(%rdi) - movq %rbx, UC_MCONTEXT_GREGS_RBX(%rdi) - - leaq 8(%rsp), %rax - movq %rax, UC_MCONTEXT_GREGS_RSP(%rdi) - - movq 0(%rsp), %rax - movq %rax, UC_MCONTEXT_GREGS_RIP(%rdi) - - xorq %rax, %rax - retq - .cfi_endproc - .size _Ux86_64_getcontext_trace, . - _Ux86_64_getcontext_trace - - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits diff --git a/contrib/libunwind/src/x86_64/init.h b/contrib/libunwind/src/x86_64/init.h deleted file mode 100644 index a7a996f1272..00000000000 --- a/contrib/libunwind/src/x86_64/init.h +++ /dev/null @@ -1,89 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002 Hewlett-Packard Co - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -/* Avoid a trip to x86_64_r_uc_addr() for purely local initialisation. */ -#if defined UNW_LOCAL_ONLY && defined __linux -# define REG_INIT_LOC(c, rlc, ruc) \ - DWARF_LOC ((unw_word_t) &c->uc->uc_mcontext.gregs[REG_ ## ruc], 0) - -#elif defined UNW_LOCAL_ONLY && defined __FreeBSD__ -# define REG_INIT_LOC(c, rlc, ruc) \ - DWARF_LOC ((unw_word_t) &c->uc->uc_mcontext.mc_ ## rlc, 0) - -#else -# define REG_INIT_LOC(c, rlc, ruc) \ - DWARF_REG_LOC (&c->dwarf, UNW_X86_64_ ## ruc) -#endif - -static inline int -common_init (struct cursor *c, unsigned use_prev_instr) -{ - int ret; - - c->dwarf.loc[RAX] = REG_INIT_LOC(c, rax, RAX); - c->dwarf.loc[RDX] = REG_INIT_LOC(c, rdx, RDX); - c->dwarf.loc[RCX] = REG_INIT_LOC(c, rcx, RCX); - c->dwarf.loc[RBX] = REG_INIT_LOC(c, rbx, RBX); - c->dwarf.loc[RSI] = REG_INIT_LOC(c, rsi, RSI); - c->dwarf.loc[RDI] = REG_INIT_LOC(c, rdi, RDI); - c->dwarf.loc[RBP] = REG_INIT_LOC(c, rbp, RBP); - c->dwarf.loc[RSP] = REG_INIT_LOC(c, rsp, RSP); - c->dwarf.loc[R8] = REG_INIT_LOC(c, r8, R8); - c->dwarf.loc[R9] = REG_INIT_LOC(c, r9, R9); - c->dwarf.loc[R10] = REG_INIT_LOC(c, r10, R10); - c->dwarf.loc[R11] = REG_INIT_LOC(c, r11, R11); - c->dwarf.loc[R12] = REG_INIT_LOC(c, r12, R12); - c->dwarf.loc[R13] = REG_INIT_LOC(c, r13, R13); - c->dwarf.loc[R14] = REG_INIT_LOC(c, r14, R14); - c->dwarf.loc[R15] = REG_INIT_LOC(c, r15, R15); - c->dwarf.loc[RIP] = REG_INIT_LOC(c, rip, RIP); - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); - if (ret < 0) - return ret; - - ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_X86_64_RSP), - &c->dwarf.cfa); - if (ret < 0) - return ret; - - c->sigcontext_format = X86_64_SCF_NONE; - c->sigcontext_addr = 0; - - c->dwarf.args_size = 0; - c->dwarf.stash_frames = 0; - c->dwarf.use_prev_instr = use_prev_instr; - c->dwarf.pi_valid = 0; - c->dwarf.pi_is_dynamic = 0; - c->dwarf.hint = 0; - c->dwarf.prev_rs = 0; - c->dwarf.eh_valid_mask = 0; - - return 0; -} diff --git a/contrib/libunwind/src/x86_64/is_fpreg.c b/contrib/libunwind/src/x86_64/is_fpreg.c deleted file mode 100644 index 1188a616f06..00000000000 --- a/contrib/libunwind/src/x86_64/is_fpreg.c +++ /dev/null @@ -1,38 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (c) 2004-2005 Hewlett-Packard Development Company, L.P. - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -PROTECTED int -unw_is_fpreg (int regnum) -{ -#if 0 - return ((regnum >= UNW_X86_ST0 && regnum <= UNW_X86_ST7) - || (regnum >= UNW_X86_XMM0_lo && regnum <= UNW_X86_XMM7_hi)); -#endif - return 0; -} diff --git a/contrib/libunwind/src/x86_64/longjmp.S b/contrib/libunwind/src/x86_64/longjmp.S deleted file mode 100644 index 274778fd80f..00000000000 --- a/contrib/libunwind/src/x86_64/longjmp.S +++ /dev/null @@ -1,34 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004-2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - - .globl _UI_longjmp_cont - .type _UI_longjmp_cont, @function -_UI_longjmp_cont: - push %rax /* push target IP as return address */ - mov %rdx, %rax /* set up return-value */ - retq - .size _UI_longjmp_cont, .-_UI_longjmp_cont - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits diff --git a/contrib/libunwind/src/x86_64/offsets.h b/contrib/libunwind/src/x86_64/offsets.h deleted file mode 100644 index 0807960f30c..00000000000 --- a/contrib/libunwind/src/x86_64/offsets.h +++ /dev/null @@ -1,3 +0,0 @@ -/* FreeBSD specific definitions */ - -#define FREEBSD_UC_MCONTEXT_OFF 0x10 diff --git a/contrib/libunwind/src/x86_64/regname.c b/contrib/libunwind/src/x86_64/regname.c deleted file mode 100644 index 6c0e2f35e4b..00000000000 --- a/contrib/libunwind/src/x86_64/regname.c +++ /dev/null @@ -1,56 +0,0 @@ -/* libunwind - a platform-independent unwind library - - Contributed by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static const char *regname[] = - { - "RAX", - "RDX", - "RCX", - "RBX", - "RSI", - "RDI", - "RBP", - "RSP", - "R8", - "R9", - "R10", - "R11", - "R12", - "R13", - "R14", - "R15", - "RIP", - }; - -PROTECTED const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) - return regname[reg]; - else - return "???"; -} diff --git a/contrib/libunwind/src/x86_64/setcontext.S b/contrib/libunwind/src/x86_64/setcontext.S deleted file mode 100644 index 358217defba..00000000000 --- a/contrib/libunwind/src/x86_64/setcontext.S +++ /dev/null @@ -1,83 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2007 Google, Inc - Contributed by Arun Sharma - Copyright (C) 2010 Konstantin Belousov - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "ucontext_i.h" - -/* int _Ux86_64_setcontext (const ucontext_t *ucp) - - Restores the machine context provided. - Unlike the libc implementation, doesn't clobber %rax - -*/ - .global _Ux86_64_setcontext - .type _Ux86_64_setcontext, @function - -_Ux86_64_setcontext: - -#if defined __linux__ - /* restore fp state */ - mov UC_MCONTEXT_FPREGS_PTR(%rdi),%r8 - fldenv (%r8) - ldmxcsr FPREGS_OFFSET_MXCSR(%r8) -#elif defined __FreeBSD__ - /* restore fp state */ - cmpq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi) - jne 1f - cmpq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi) - jne 1f - fxrstor UC_MCONTEXT_FPSTATE(%rdi) -1: -#else -#error Port me -#endif - - /* restore the rest of the state */ - mov UC_MCONTEXT_GREGS_R8(%rdi),%r8 - mov UC_MCONTEXT_GREGS_R9(%rdi),%r9 - mov UC_MCONTEXT_GREGS_RBX(%rdi),%rbx - mov UC_MCONTEXT_GREGS_RBP(%rdi),%rbp - mov UC_MCONTEXT_GREGS_R12(%rdi),%r12 - mov UC_MCONTEXT_GREGS_R13(%rdi),%r13 - mov UC_MCONTEXT_GREGS_R14(%rdi),%r14 - mov UC_MCONTEXT_GREGS_R15(%rdi),%r15 - mov UC_MCONTEXT_GREGS_RSI(%rdi),%rsi - mov UC_MCONTEXT_GREGS_RDX(%rdi),%rdx - mov UC_MCONTEXT_GREGS_RAX(%rdi),%rax - mov UC_MCONTEXT_GREGS_RCX(%rdi),%rcx - mov UC_MCONTEXT_GREGS_RSP(%rdi),%rsp - - /* push the return address on the stack */ - mov UC_MCONTEXT_GREGS_RIP(%rdi),%rcx - push %rcx - - mov UC_MCONTEXT_GREGS_RCX(%rdi),%rcx - mov UC_MCONTEXT_GREGS_RDI(%rdi),%rdi - retq - - .size _Ux86_64_setcontext, . - _Ux86_64_setcontext - - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits diff --git a/contrib/libunwind/src/x86_64/siglongjmp.S b/contrib/libunwind/src/x86_64/siglongjmp.S deleted file mode 100644 index 32489e53a9f..00000000000 --- a/contrib/libunwind/src/x86_64/siglongjmp.S +++ /dev/null @@ -1,32 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - - .globl _UI_siglongjmp_cont - .type _UI_siglongjmp_cont, @function -_UI_siglongjmp_cont: - retq - .size _UI_siglongjmp_cont, . - _UI_siglongjmp_cont - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits diff --git a/contrib/libunwind/src/x86_64/ucontext_i.h b/contrib/libunwind/src/x86_64/ucontext_i.h deleted file mode 100644 index aded941d053..00000000000 --- a/contrib/libunwind/src/x86_64/ucontext_i.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright (C) 2004 Hewlett-Packard Co. - Contributed by David Mosberger-Tang . - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#if defined __linux__ -#define UC_MCONTEXT_GREGS_R8 0x28 -#define UC_MCONTEXT_GREGS_R9 0x30 -#define UC_MCONTEXT_GREGS_R10 0x38 -#define UC_MCONTEXT_GREGS_R11 0x40 -#define UC_MCONTEXT_GREGS_R12 0x48 -#define UC_MCONTEXT_GREGS_R13 0x50 -#define UC_MCONTEXT_GREGS_R14 0x58 -#define UC_MCONTEXT_GREGS_R15 0x60 -#define UC_MCONTEXT_GREGS_RDI 0x68 -#define UC_MCONTEXT_GREGS_RSI 0x70 -#define UC_MCONTEXT_GREGS_RBP 0x78 -#define UC_MCONTEXT_GREGS_RBX 0x80 -#define UC_MCONTEXT_GREGS_RDX 0x88 -#define UC_MCONTEXT_GREGS_RAX 0x90 -#define UC_MCONTEXT_GREGS_RCX 0x98 -#define UC_MCONTEXT_GREGS_RSP 0xa0 -#define UC_MCONTEXT_GREGS_RIP 0xa8 -#define UC_MCONTEXT_FPREGS_PTR 0x1a8 -#define UC_MCONTEXT_FPREGS_MEM 0xe0 -#define UC_SIGMASK 0x128 -#define FPREGS_OFFSET_MXCSR 0x18 -#elif defined __FreeBSD__ -#define UC_SIGMASK 0x0 -#define UC_MCONTEXT_GREGS_RDI 0x18 -#define UC_MCONTEXT_GREGS_RSI 0x20 -#define UC_MCONTEXT_GREGS_RDX 0x28 -#define UC_MCONTEXT_GREGS_RCX 0x30 -#define UC_MCONTEXT_GREGS_R8 0x38 -#define UC_MCONTEXT_GREGS_R9 0x40 -#define UC_MCONTEXT_GREGS_RAX 0x48 -#define UC_MCONTEXT_GREGS_RBX 0x50 -#define UC_MCONTEXT_GREGS_RBP 0x58 -#define UC_MCONTEXT_GREGS_R10 0x60 -#define UC_MCONTEXT_GREGS_R11 0x68 -#define UC_MCONTEXT_GREGS_R12 0x70 -#define UC_MCONTEXT_GREGS_R13 0x78 -#define UC_MCONTEXT_GREGS_R14 0x80 -#define UC_MCONTEXT_GREGS_R15 0x88 -#define UC_MCONTEXT_FS 0x94 -#define UC_MCONTEXT_GS 0x96 -#define UC_MCONTEXT_FLAGS 0xa0 -#define UC_MCONTEXT_ES 0xa4 -#define UC_MCONTEXT_DS 0xa6 -#define UC_MCONTEXT_GREGS_RIP 0xb0 -#define UC_MCONTEXT_CS 0xb8 -#define UC_MCONTEXT_RFLAGS 0xc0 -#define UC_MCONTEXT_GREGS_RSP 0xc8 -#define UC_MCONTEXT_SS 0xd0 -#define UC_MCONTEXT_MC_LEN 0xd8 -#define UC_MCONTEXT_FPFORMAT 0xe0 -#define UC_MCONTEXT_OWNEDFP 0xe8 -#define UC_MCONTEXT_FPSTATE 0xf0 -#define UC_MCONTEXT_FPOWNED_FPU 0x20001 -#define UC_MCONTEXT_FPFMT_XMM 0x10002 -#define UC_MCONTEXT_MC_LEN_VAL 0x320 - -#endif diff --git a/contrib/libunwind/src/x86_64/unwind_i.h b/contrib/libunwind/src/x86_64/unwind_i.h deleted file mode 100644 index 4f81566ad02..00000000000 --- a/contrib/libunwind/src/x86_64/unwind_i.h +++ /dev/null @@ -1,91 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002, 2005 Hewlett-Packard Co - Contributed by David Mosberger-Tang - - Modified for x86_64 by Max Asbock - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include - -#include - -#include "libunwind_i.h" -#include - -/* DWARF column numbers for x86_64: */ -#define RAX 0 -#define RDX 1 -#define RCX 2 -#define RBX 3 -#define RSI 4 -#define RDI 5 -#define RBP 6 -#define RSP 7 -#define R8 8 -#define R9 9 -#define R10 10 -#define R11 11 -#define R12 12 -#define R13 13 -#define R14 14 -#define R15 15 -#define RIP 16 - -#define x86_64_lock UNW_OBJ(lock) -#define x86_64_local_resume UNW_OBJ(local_resume) -#define x86_64_local_addr_space_init UNW_OBJ(local_addr_space_init) -#define setcontext UNW_ARCH_OBJ (setcontext) -#if 0 -#define x86_64_scratch_loc UNW_OBJ(scratch_loc) -#endif -#define x86_64_r_uc_addr UNW_OBJ(r_uc_addr) -#define x86_64_sigreturn UNW_OBJ(sigreturn) - -/* By-pass calls to access_mem() when known to be safe. */ -#ifdef UNW_LOCAL_ONLY -# undef ACCESS_MEM_FAST -# define ACCESS_MEM_FAST(ret,validate,cur,addr,to) \ - do { \ - if (unlikely(validate)) \ - (ret) = dwarf_get ((cur), DWARF_MEM_LOC ((cur), (addr)), &(to)); \ - else \ - (ret) = 0, (to) = *(unw_word_t *)(addr); \ - } while (0) -#endif - -extern void x86_64_local_addr_space_init (void); -extern int x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, - void *arg); -extern int setcontext (const ucontext_t *ucp); - -#if 0 -extern dwarf_loc_t x86_64_scratch_loc (struct cursor *c, unw_regnum_t reg); -#endif - -extern void *x86_64_r_uc_addr (ucontext_t *uc, int reg); -extern NORETURN void x86_64_sigreturn (unw_cursor_t *cursor); - -#endif /* unwind_i_h */ diff --git a/contrib/poco b/contrib/poco index 29439cf7fa3..ece721f1085 160000 --- a/contrib/poco +++ b/contrib/poco @@ -1 +1 @@ -Subproject commit 29439cf7fa32c1a2d62d925bb6d6a3f14668a4a2 +Subproject commit ece721f1085e3894cb5286e8560af84cd1445326 diff --git a/contrib/simdjson b/contrib/simdjson index 2151ad7f34c..3bd3116cf8f 160000 --- a/contrib/simdjson +++ b/contrib/simdjson @@ -1 +1 @@ -Subproject commit 2151ad7f34cf773a23f086e941d661f8a8873144 +Subproject commit 3bd3116cf8faf6d482dc31423b16533bfa2696f7 diff --git a/contrib/simdjson-cmake/CMakeLists.txt b/contrib/simdjson-cmake/CMakeLists.txt index 16a5dc1a791..bbb2d8e389f 100644 --- a/contrib/simdjson-cmake/CMakeLists.txt +++ b/contrib/simdjson-cmake/CMakeLists.txt @@ -11,8 +11,9 @@ set(SIMDJSON_SRC ${SIMDJSON_SRC_DIR}/stage2_build_tape.cpp ${SIMDJSON_SRC_DIR}/parsedjson.cpp ${SIMDJSON_SRC_DIR}/parsedjsoniterator.cpp + ${SIMDJSON_SRC_DIR}/simdjson.cpp ) add_library(${SIMDJSON_LIBRARY} ${SIMDJSON_SRC}) -target_include_directories(${SIMDJSON_LIBRARY} PUBLIC "${SIMDJSON_INCLUDE_DIR}") +target_include_directories(${SIMDJSON_LIBRARY} SYSTEM PUBLIC "${SIMDJSON_INCLUDE_DIR}") target_compile_options(${SIMDJSON_LIBRARY} PRIVATE -mavx2 -mbmi -mbmi2 -mpclmul) diff --git a/dbms/CMakeLists.txt b/dbms/CMakeLists.txt index 4b47b77dec2..c0dbec3da74 100644 --- a/dbms/CMakeLists.txt +++ b/dbms/CMakeLists.txt @@ -2,6 +2,10 @@ if (USE_INCLUDE_WHAT_YOU_USE) set (CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${IWYU_PATH}) endif () +if (USE_CLANG_TIDY) + set (CMAKE_CXX_CLANG_TIDY "${DO_CLANG_TIDY}") +endif () + if(COMPILER_PIPE) set(MAX_COMPILER_MEMORY 2500) else() @@ -44,7 +48,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow -Wshadow-uncaptured-local -Wextra-semi -Wcomma -Winconsistent-missing-destructor-override -Wunused-exception-parameter -Wcovered-switch-default -Wold-style-cast -Wrange-loop-analysis -Wunused-member-function -Wunreachable-code -Wunreachable-code-return -Wnewline-eof -Wembedded-directive -Wgnu-case-range -Wunused-macros -Wconditional-uninitialized -Wdeprecated -Wundef -Wreserved-id-macro -Wredundant-parens -Wzero-as-null-pointer-constant") if (WEVERYTHING) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-missing-noreturn -Wno-padded -Wno-switch-enum -Wno-shadow-field-in-constructor -Wno-deprecated-dynamic-exception-spec -Wno-float-equal -Wno-weak-vtables -Wno-shift-sign-overflow -Wno-sign-conversion -Wno-conversion -Wno-exit-time-destructors -Wno-undefined-func-template -Wno-documentation-unknown-command -Wno-missing-variable-declarations -Wno-unused-template -Wno-global-constructors -Wno-c99-extensions -Wno-missing-prototypes -Wno-weak-template-vtables -Wno-zero-length-array -Wno-gnu-anonymous-struct -Wno-nested-anon-types -Wno-double-promotion -Wno-disabled-macro-expansion -Wno-used-but-marked-unused -Wno-vla-extension -Wno-vla -Wno-packed") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-switch-enum -Wno-shadow-field-in-constructor -Wno-deprecated-dynamic-exception-spec -Wno-float-equal -Wno-weak-vtables -Wno-shift-sign-overflow -Wno-sign-conversion -Wno-conversion -Wno-exit-time-destructors -Wno-undefined-func-template -Wno-documentation-unknown-command -Wno-missing-variable-declarations -Wno-unused-template -Wno-global-constructors -Wno-c99-extensions -Wno-missing-prototypes -Wno-weak-template-vtables -Wno-zero-length-array -Wno-gnu-anonymous-struct -Wno-nested-anon-types -Wno-double-promotion -Wno-disabled-macro-expansion -Wno-vla-extension -Wno-vla -Wno-packed") # TODO Enable conversion, sign-conversion, double-promotion warnings. endif () @@ -98,6 +102,7 @@ add_headers_and_sources(clickhouse_common_io src/Common/HashTable) add_headers_and_sources(clickhouse_common_io src/IO) add_headers_and_sources(dbms src/Core) +add_headers_and_sources(dbms src/Compression/) add_headers_and_sources(dbms src/DataStreams) add_headers_and_sources(dbms src/DataTypes) add_headers_and_sources(dbms src/Databases) @@ -109,6 +114,18 @@ add_headers_and_sources(dbms src/Storages/Distributed) add_headers_and_sources(dbms src/Storages/MergeTree) add_headers_and_sources(dbms src/Client) add_headers_and_sources(dbms src/Formats) +add_headers_and_sources(dbms src/Processors) +add_headers_and_sources(dbms src/Processors/Executors) +add_headers_and_sources(dbms src/Processors/Formats) +add_headers_and_sources(dbms src/Processors/Formats/Impl) +add_headers_and_sources(dbms src/Processors/Transforms) +add_headers_and_sources(dbms src/Processors/Sources) +add_headers_only(dbms src/Server) + +if(USE_RDKAFKA) + add_headers_and_sources(dbms src/Storages/Kafka) +endif() + list (APPEND clickhouse_common_io_sources ${CONFIG_BUILD}) list (APPEND clickhouse_common_io_headers ${CONFIG_VERSION} ${CONFIG_COMMON}) @@ -218,6 +235,17 @@ target_link_libraries(clickhouse_common_io roaring ) +if(ZSTD_LIBRARY) + target_link_libraries(clickhouse_common_io PRIVATE ${ZSTD_LIBRARY}) +endif() + +if (USE_RDKAFKA) + target_link_libraries(dbms PRIVATE ${CPPKAFKA_LIBRARY} ${RDKAFKA_LIBRARY}) + if(NOT USE_INTERNAL_RDKAFKA_LIBRARY) + target_include_directories(dbms SYSTEM BEFORE PRIVATE ${RDKAFKA_INCLUDE_DIR}) + endif() +endif() + if(RE2_INCLUDE_DIR) target_include_directories(clickhouse_common_io SYSTEM BEFORE PUBLIC ${RE2_INCLUDE_DIR}) @@ -237,28 +265,43 @@ if(CPUINFO_LIBRARY) endif() target_link_libraries (dbms - PUBLIC - clickhouse_compression PRIVATE clickhouse_parsers clickhouse_common_config + clickhouse_common_zookeeper + string_utils # FIXME: not sure if it's private PUBLIC clickhouse_common_io PRIVATE clickhouse_dictionaries_embedded + ${LZ4_LIBRARY} PUBLIC ${MYSQLXX_LIBRARY} PRIVATE ${BTRIE_LIBRARIES} ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} PUBLIC ${Boost_SYSTEM_LIBRARY} Threads::Threads ) +if(ZSTD_LIBRARY) + target_link_libraries(clickhouse_common_io PRIVATE ${ZSTD_LIBRARY}) +endif() + target_include_directories(dbms PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/src/Core/include) target_include_directories(clickhouse_common_io PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/src/Core/include) # uses some includes from core target_include_directories(dbms SYSTEM BEFORE PUBLIC ${PDQSORT_INCLUDE_DIR}) +target_include_directories(dbms SYSTEM PUBLIC ${PCG_RANDOM_INCLUDE_DIR}) + +if (NOT USE_INTERNAL_LZ4_LIBRARY) + target_include_directories(dbms SYSTEM BEFORE PRIVATE ${LZ4_INCLUDE_DIR}) +endif () +if (NOT USE_INTERNAL_ZSTD_LIBRARY AND ZSTD_INCLUDE_DIR) + target_include_directories(dbms SYSTEM BEFORE PRIVATE ${ZSTD_INCLUDE_DIR}) +endif () + if (NOT USE_INTERNAL_BOOST_LIBRARY) target_include_directories (clickhouse_common_io SYSTEM BEFORE PUBLIC ${Boost_INCLUDE_DIRS}) @@ -314,10 +357,6 @@ if (USE_CAPNP) endif () endif () -if (USE_RDKAFKA) - target_link_libraries (dbms PRIVATE clickhouse_storage_kafka) -endif () - if (USE_PARQUET) target_link_libraries(dbms PRIVATE ${PARQUET_LIBRARY}) if (NOT USE_INTERNAL_PARQUET_LIBRARY OR USE_INTERNAL_PARQUET_LIBRARY_NATIVE_CMAKE) @@ -372,6 +411,10 @@ if (ENABLE_TESTS AND USE_GTEST) # attach all dbms gtest sources grep_gtest_sources(${ClickHouse_SOURCE_DIR}/dbms dbms_gtest_sources) add_executable(unit_tests_dbms ${dbms_gtest_sources}) + + # gtest framework has substandard code + target_compile_options(unit_tests_dbms PRIVATE -Wno-zero-as-null-pointer-constant -Wno-undef -Wno-sign-compare -Wno-used-but-marked-unused -Wno-missing-noreturn) + target_link_libraries(unit_tests_dbms PRIVATE ${GTEST_BOTH_LIBRARIES} clickhouse_functions clickhouse_parsers dbms clickhouse_common_zookeeper) add_check(unit_tests_dbms) endif () diff --git a/dbms/cmake/version.cmake b/dbms/cmake/version.cmake index 77503018203..5714b5207b8 100644 --- a/dbms/cmake/version.cmake +++ b/dbms/cmake/version.cmake @@ -1,11 +1,11 @@ # This strings autochanged from release_lib.sh: -set(VERSION_REVISION 54423) +set(VERSION_REVISION 54424) set(VERSION_MAJOR 19) -set(VERSION_MINOR 11) -set(VERSION_PATCH 0) -set(VERSION_GITHASH badb6ab8310ed94e20f43ac9a9a227f7a2590009) -set(VERSION_DESCRIBE v19.11.0-testing) -set(VERSION_STRING 19.11.0) +set(VERSION_MINOR 12) +set(VERSION_PATCH 1) +set(VERSION_GITHASH a584f0ca6cb5df9b0d9baf1e2e1eaa7d12a20a44) +set(VERSION_DESCRIBE v19.12.1.1-prestable) +set(VERSION_STRING 19.12.1.1) # end of autochange set(VERSION_EXTRA "" CACHE STRING "") diff --git a/dbms/programs/benchmark/Benchmark.cpp b/dbms/programs/benchmark/Benchmark.cpp index 019080e2391..c69e9a54feb 100644 --- a/dbms/programs/benchmark/Benchmark.cpp +++ b/dbms/programs/benchmark/Benchmark.cpp @@ -61,6 +61,8 @@ public: randomize(randomize_), max_iterations(max_iterations_), max_time(max_time_), json_path(json_path_), settings(settings_), global_context(Context::createGlobal()), pool(concurrency) { + global_context.makeGlobalContext(); + std::cerr << std::fixed << std::setprecision(3); /// This is needed to receive blocks with columns of AggregateFunction data type diff --git a/dbms/programs/benchmark/CMakeLists.txt b/dbms/programs/benchmark/CMakeLists.txt index ccbefc0453a..58096985037 100644 --- a/dbms/programs/benchmark/CMakeLists.txt +++ b/dbms/programs/benchmark/CMakeLists.txt @@ -1,5 +1,5 @@ set(CLICKHOUSE_BENCHMARK_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Benchmark.cpp) -set(CLICKHOUSE_BENCHMARK_LINK PRIVATE clickhouse_aggregate_functions clickhouse_common_config clickhouse_common_io ${Boost_PROGRAM_OPTIONS_LIBRARY}) +set(CLICKHOUSE_BENCHMARK_LINK PRIVATE dbms clickhouse_aggregate_functions clickhouse_common_config ${Boost_PROGRAM_OPTIONS_LIBRARY}) set(CLICKHOUSE_BENCHMARK_INCLUDE SYSTEM PRIVATE ${PCG_RANDOM_INCLUDE_DIR}) clickhouse_program_add(benchmark) diff --git a/dbms/programs/client/CMakeLists.txt b/dbms/programs/client/CMakeLists.txt index 06b142227d7..88e23a094d1 100644 --- a/dbms/programs/client/CMakeLists.txt +++ b/dbms/programs/client/CMakeLists.txt @@ -3,7 +3,7 @@ set(CLICKHOUSE_CLIENT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/ConnectionParameters.cpp ) -set(CLICKHOUSE_CLIENT_LINK PRIVATE clickhouse_common_config clickhouse_functions clickhouse_aggregate_functions clickhouse_common_io ${LINE_EDITING_LIBS} ${Boost_PROGRAM_OPTIONS_LIBRARY}) +set(CLICKHOUSE_CLIENT_LINK PRIVATE clickhouse_common_config clickhouse_functions clickhouse_aggregate_functions clickhouse_common_io clickhouse_parsers string_utils ${LINE_EDITING_LIBS} ${Boost_PROGRAM_OPTIONS_LIBRARY}) set(CLICKHOUSE_CLIENT_INCLUDE SYSTEM PRIVATE ${READLINE_INCLUDE_DIR} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include) include(CheckSymbolExists) diff --git a/dbms/programs/client/Client.cpp b/dbms/programs/client/Client.cpp index 69cdf5b1355..091a1ac063f 100644 --- a/dbms/programs/client/Client.cpp +++ b/dbms/programs/client/Client.cpp @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -202,6 +203,9 @@ private: /// External tables info. std::list external_tables; + /// Dictionary with query parameters for prepared statements. + NameToNameMap query_parameters; + ConnectionParameters connection_parameters; void initialize(Poco::Util::Application & self) @@ -214,6 +218,7 @@ private: configReadClient(config(), home_path); + context.makeGlobalContext(); context.setApplicationType(Context::ApplicationType::CLIENT); /// settings and limits could be specified in config file, but passed settings has higher priority @@ -795,7 +800,6 @@ private: /// Some parts of a query (result output and formatting) are executed client-side. /// Thus we need to parse the query. parsed_query = parsed_query_; - if (!parsed_query) { const char * begin = query.data(); @@ -900,6 +904,16 @@ private: /// Process the query that doesn't require transferring data blocks to the server. void processOrdinaryQuery() { + /// We will always rewrite query (even if there are no query_parameters) because it will help to find errors in query formatter. + { + /// Replace ASTQueryParameter with ASTLiteral for prepared statements. + ReplaceQueryParameterVisitor visitor(query_parameters); + visitor.visit(parsed_query); + + /// Get new query after substitutions. Note that it cannot be done for INSERT query with embedded data. + query = serializeAST(*parsed_query); + } + connection->sendQuery(connection_parameters.timeouts, query, query_id, QueryProcessingStage::Complete, &context.getSettingsRef(), nullptr, true); sendExternalTables(); receiveResult(); @@ -1548,7 +1562,8 @@ public: /** We allow different groups of arguments: * - common arguments; * - arguments for any number of external tables each in form "--external args...", - * where possible args are file, name, format, structure, types. + * where possible args are file, name, format, structure, types; + * - param arguments for prepared statements. * Split these groups before processing. */ using Arguments = std::vector; @@ -1597,7 +1612,31 @@ public: else { in_external_group = false; - common_arguments.emplace_back(arg); + + /// Parameter arg after underline. + if (startsWith(arg, "--param_")) + { + const char * param_continuation = arg + strlen("--param_"); + const char * equal_pos = strchr(param_continuation, '='); + + if (equal_pos == param_continuation) + throw Exception("Parameter name cannot be empty", ErrorCodes::BAD_ARGUMENTS); + + if (equal_pos) + { + /// param_name=value + query_parameters.emplace(String(param_continuation, equal_pos), String(equal_pos + 1)); + } + else + { + /// param_name value + ++arg_num; + arg = argv[arg_num]; + query_parameters.emplace(String(param_continuation), String(arg)); + } + } + else + common_arguments.emplace_back(arg); } } @@ -1672,6 +1711,7 @@ public: ("structure", po::value(), "structure") ("types", po::value(), "types") ; + /// Parse main commandline options. po::parsed_options parsed = po::command_line_parser(common_arguments).options(main_description).run(); po::variables_map options; @@ -1696,6 +1736,7 @@ public: { std::cout << main_description << "\n"; std::cout << external_description << "\n"; + std::cout << "In addition, --param_name=value can be specified for substitution of parameters for parametrized queries.\n"; exit(0); } diff --git a/dbms/programs/client/readpassphrase/readpassphrase.h b/dbms/programs/client/readpassphrase/readpassphrase.h index d504cff5f00..272c822423a 100644 --- a/dbms/programs/client/readpassphrase/readpassphrase.h +++ b/dbms/programs/client/readpassphrase/readpassphrase.h @@ -29,6 +29,11 @@ //#include "includes.h" #include "config_client.h" +// Should not be included on BSD systems, but if it happen... +#ifdef HAVE_READPASSPHRASE +# include_next +#endif + #ifndef HAVE_READPASSPHRASE # ifdef __cplusplus diff --git a/dbms/programs/compressor/CMakeLists.txt b/dbms/programs/compressor/CMakeLists.txt index 46fd4816ba2..c009bb55f76 100644 --- a/dbms/programs/compressor/CMakeLists.txt +++ b/dbms/programs/compressor/CMakeLists.txt @@ -1,7 +1,7 @@ # Also in utils set(CLICKHOUSE_COMPRESSOR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Compressor.cpp) -set(CLICKHOUSE_COMPRESSOR_LINK PRIVATE clickhouse_compression clickhouse_common_io ${Boost_PROGRAM_OPTIONS_LIBRARY}) +set(CLICKHOUSE_COMPRESSOR_LINK PRIVATE dbms clickhouse_parsers ${Boost_PROGRAM_OPTIONS_LIBRARY}) #set(CLICKHOUSE_COMPRESSOR_INCLUDE SYSTEM PRIVATE ...) clickhouse_program_add(compressor) diff --git a/dbms/programs/copier/CMakeLists.txt b/dbms/programs/copier/CMakeLists.txt index 0aec381ebd5..85b2819ac7a 100644 --- a/dbms/programs/copier/CMakeLists.txt +++ b/dbms/programs/copier/CMakeLists.txt @@ -1,5 +1,5 @@ set(CLICKHOUSE_COPIER_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/ClusterCopier.cpp) -set(CLICKHOUSE_COPIER_LINK PRIVATE clickhouse_functions clickhouse_table_functions clickhouse_aggregate_functions clickhouse_dictionaries PUBLIC daemon) +set(CLICKHOUSE_COPIER_LINK PRIVATE clickhouse_common_zookeeper clickhouse_parsers clickhouse_functions clickhouse_table_functions clickhouse_aggregate_functions clickhouse_dictionaries string_utils PUBLIC daemon) set(CLICKHOUSE_COPIER_INCLUDE SYSTEM PRIVATE ${PCG_RANDOM_INCLUDE_DIR}) clickhouse_program_add(copier) diff --git a/dbms/programs/copier/ClusterCopier.cpp b/dbms/programs/copier/ClusterCopier.cpp index e4bdbfac7dc..43158dedd71 100644 --- a/dbms/programs/copier/ClusterCopier.cpp +++ b/dbms/programs/copier/ClusterCopier.cpp @@ -2171,10 +2171,10 @@ void ClusterCopierApp::mainImpl() << "revision " << ClickHouseRevision::get() << ")"); auto context = std::make_unique(Context::createGlobal()); + context->makeGlobalContext(); SCOPE_EXIT(context->shutdown()); context->setConfig(loaded_config.configuration); - context->setGlobalContext(*context); context->setApplicationType(Context::ApplicationType::LOCAL); context->setPath(process_path); @@ -2201,6 +2201,10 @@ void ClusterCopierApp::mainImpl() copier->init(); copier->process(ConnectionTimeouts::getTCPTimeoutsWithoutFailover(context->getSettingsRef())); + + /// Reset ZooKeeper before removing ClusterCopier. + /// Otherwise zookeeper watch can call callback which use already removed ClusterCopier object. + context->resetZooKeeper(); } diff --git a/dbms/programs/extract-from-config/CMakeLists.txt b/dbms/programs/extract-from-config/CMakeLists.txt index 4c01cd9c999..b82cbb966ae 100644 --- a/dbms/programs/extract-from-config/CMakeLists.txt +++ b/dbms/programs/extract-from-config/CMakeLists.txt @@ -1,5 +1,5 @@ set(CLICKHOUSE_EXTRACT_FROM_CONFIG_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/ExtractFromConfig.cpp) -set(CLICKHOUSE_EXTRACT_FROM_CONFIG_LINK PRIVATE clickhouse_common_config clickhouse_common_io ${Boost_PROGRAM_OPTIONS_LIBRARY}) +set(CLICKHOUSE_EXTRACT_FROM_CONFIG_LINK PRIVATE clickhouse_common_config clickhouse_common_io clickhouse_common_zookeeper ${Boost_PROGRAM_OPTIONS_LIBRARY}) #set(CLICKHOUSE_EXTRACT_FROM_CONFIG_INCLUDE SYSTEM PRIVATE ...) clickhouse_program_add(extract-from-config) diff --git a/dbms/programs/local/CMakeLists.txt b/dbms/programs/local/CMakeLists.txt index 41780936977..d066fd53277 100644 --- a/dbms/programs/local/CMakeLists.txt +++ b/dbms/programs/local/CMakeLists.txt @@ -1,5 +1,5 @@ set(CLICKHOUSE_LOCAL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/LocalServer.cpp) -set(CLICKHOUSE_LOCAL_LINK PRIVATE clickhouse_dictionaries clickhouse_common_io clickhouse_functions clickhouse_aggregate_functions clickhouse_table_functions ${Boost_PROGRAM_OPTIONS_LIBRARY}) +set(CLICKHOUSE_LOCAL_LINK PRIVATE clickhouse_storages_system clickhouse_dictionaries clickhouse_common_config clickhouse_common_io clickhouse_functions clickhouse_aggregate_functions clickhouse_parsers clickhouse_table_functions ${Boost_PROGRAM_OPTIONS_LIBRARY}) #set(CLICKHOUSE_LOCAL_INCLUDE SYSTEM PRIVATE ...) clickhouse_program_add(local) diff --git a/dbms/programs/local/LocalServer.cpp b/dbms/programs/local/LocalServer.cpp index 3e3b249fe82..bed55a0fc5f 100644 --- a/dbms/programs/local/LocalServer.cpp +++ b/dbms/programs/local/LocalServer.cpp @@ -131,7 +131,7 @@ try context = std::make_unique(Context::createGlobal()); - context->setGlobalContext(*context); + context->makeGlobalContext(); context->setApplicationType(Context::ApplicationType::LOCAL); tryInitPath(); @@ -275,8 +275,8 @@ void LocalServer::processQueries() if (!parse_res.second) throw Exception("Cannot parse and execute the following part of query: " + String(parse_res.first), ErrorCodes::SYNTAX_ERROR); - context->setSessionContext(*context); - context->setQueryContext(*context); + context->makeSessionContext(); + context->makeQueryContext(); context->setUser("default", "", Poco::Net::SocketAddress{}, ""); context->setCurrentQueryId(""); diff --git a/dbms/programs/obfuscator/Obfuscator.cpp b/dbms/programs/obfuscator/Obfuscator.cpp index 7488433d569..3c20510d481 100644 --- a/dbms/programs/obfuscator/Obfuscator.cpp +++ b/dbms/programs/obfuscator/Obfuscator.cpp @@ -1024,6 +1024,7 @@ try } Context context = Context::createGlobal(); + context.makeGlobalContext(); ReadBufferFromFileDescriptor file_in(STDIN_FILENO); WriteBufferFromFileDescriptor file_out(STDOUT_FILENO); diff --git a/dbms/programs/odbc-bridge/CMakeLists.txt b/dbms/programs/odbc-bridge/CMakeLists.txt index 90aad184f3e..060a36e9275 100644 --- a/dbms/programs/odbc-bridge/CMakeLists.txt +++ b/dbms/programs/odbc-bridge/CMakeLists.txt @@ -11,7 +11,7 @@ set(CLICKHOUSE_ODBC_BRIDGE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/validateODBCConnectionString.cpp ) -set(CLICKHOUSE_ODBC_BRIDGE_LINK PRIVATE dbms clickhouse_common_io PUBLIC daemon) +set(CLICKHOUSE_ODBC_BRIDGE_LINK PRIVATE dbms clickhouse_parsers PUBLIC daemon) set(CLICKHOUSE_ODBC_BRIDGE_INCLUDE PUBLIC ${ClickHouse_SOURCE_DIR}/libs/libdaemon/include) if (USE_POCO_SQLODBC) diff --git a/dbms/programs/odbc-bridge/ODBCBridge.cpp b/dbms/programs/odbc-bridge/ODBCBridge.cpp index aaacdfca826..cf265eb6abb 100644 --- a/dbms/programs/odbc-bridge/ODBCBridge.cpp +++ b/dbms/programs/odbc-bridge/ODBCBridge.cpp @@ -160,7 +160,7 @@ int ODBCBridge::main(const std::vector & /*args*/) http_params->setKeepAliveTimeout(keep_alive_timeout); context = std::make_shared(Context::createGlobal()); - context->setGlobalContext(*context); + context->makeGlobalContext(); auto server = Poco::Net::HTTPServer( new HandlerFactory("ODBCRequestHandlerFactory-factory", keep_alive_timeout, context), server_pool, socket, http_params); diff --git a/dbms/programs/performance-test/CMakeLists.txt b/dbms/programs/performance-test/CMakeLists.txt index c7eeaa45ab3..94e346c83cd 100644 --- a/dbms/programs/performance-test/CMakeLists.txt +++ b/dbms/programs/performance-test/CMakeLists.txt @@ -1,4 +1,4 @@ -set(CLICKHOUSE_PERFORMANCE_TEST_SOURCES +set(CLICKHOUSE_PERFORMANCE_TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/JSONString.cpp ${CMAKE_CURRENT_SOURCE_DIR}/StopConditionsSet.cpp ${CMAKE_CURRENT_SOURCE_DIR}/TestStopConditions.cpp @@ -12,7 +12,7 @@ set(CLICKHOUSE_PERFORMANCE_TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/PerformanceTestSuite.cpp ) -set(CLICKHOUSE_PERFORMANCE_TEST_LINK PRIVATE dbms clickhouse_common_io clickhouse_common_config ${Boost_PROGRAM_OPTIONS_LIBRARY}) +set(CLICKHOUSE_PERFORMANCE_TEST_LINK PRIVATE dbms clickhouse_common_config ${Boost_FILESYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) set(CLICKHOUSE_PERFORMANCE_TEST_INCLUDE SYSTEM PRIVATE ${PCG_RANDOM_INCLUDE_DIR}) clickhouse_program_add(performance-test) diff --git a/dbms/programs/performance-test/PerformanceTestSuite.cpp b/dbms/programs/performance-test/PerformanceTestSuite.cpp index cfa7d202d1d..5f5c13f3390 100644 --- a/dbms/programs/performance-test/PerformanceTestSuite.cpp +++ b/dbms/programs/performance-test/PerformanceTestSuite.cpp @@ -89,6 +89,7 @@ public: , input_files(input_files_) , log(&Poco::Logger::get("PerformanceTestSuite")) { + global_context.makeGlobalContext(); global_context.getSettingsRef().copyChangesFrom(cmd_settings); if (input_files.size() < 1) throw Exception("No tests were specified", ErrorCodes::BAD_ARGUMENTS); diff --git a/dbms/programs/server/CMakeLists.txt b/dbms/programs/server/CMakeLists.txt index fe260c1192d..72a2427ef3c 100644 --- a/dbms/programs/server/CMakeLists.txt +++ b/dbms/programs/server/CMakeLists.txt @@ -8,11 +8,17 @@ set(CLICKHOUSE_SERVER_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/RootRequestHandler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Server.cpp ${CMAKE_CURRENT_SOURCE_DIR}/TCPHandler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/MySQLHandler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/MySQLHandlerFactory.cpp ) -set(CLICKHOUSE_SERVER_LINK PRIVATE clickhouse_dictionaries clickhouse_common_io PUBLIC daemon PRIVATE clickhouse_storages_system clickhouse_functions clickhouse_aggregate_functions clickhouse_table_functions ${Poco_Net_LIBRARY}) +if (USE_POCO_NETSSL) + set(CLICKHOUSE_SERVER_SOURCES + ${CLICKHOUSE_SERVER_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/MySQLHandler.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/MySQLHandlerFactory.cpp + ) +endif () + +set(CLICKHOUSE_SERVER_LINK PRIVATE clickhouse_dictionaries clickhouse_common_io clickhouse_common_config clickhouse_common_zookeeper clickhouse_parsers string_utils PUBLIC daemon PRIVATE clickhouse_storages_system clickhouse_functions clickhouse_aggregate_functions clickhouse_table_functions ${Poco_Net_LIBRARY}) if (USE_POCO_NETSSL) set(CLICKHOUSE_SERVER_LINK ${CLICKHOUSE_SERVER_LINK} PRIVATE ${Poco_NetSSL_LIBRARY} ${Poco_Crypto_LIBRARY}) endif () diff --git a/dbms/programs/server/HTTPHandler.cpp b/dbms/programs/server/HTTPHandler.cpp index 048f175160b..5db7ce1a3ae 100644 --- a/dbms/programs/server/HTTPHandler.cpp +++ b/dbms/programs/server/HTTPHandler.cpp @@ -211,7 +211,6 @@ void HTTPHandler::processQuery( Output & used_output) { Context context = server.context(); - context.setGlobalContext(server.context()); CurrentThread::QueryScope query_scope(context); @@ -475,9 +474,9 @@ void HTTPHandler::processQuery( settings.readonly = 2; } - bool isExternalData = startsWith(request.getContentType().data(), "multipart/form-data"); + bool has_external_data = startsWith(request.getContentType().data(), "multipart/form-data"); - if (isExternalData) + if (has_external_data) { /// Skip unneeded parameters to avoid confusing them later with context settings or query parameters. reserved_param_suffixes.reserve(3); @@ -501,6 +500,12 @@ void HTTPHandler::processQuery( else if (param_could_be_skipped(key)) { } + else if (startsWith(key, "param_")) + { + /// Save name and values of substitution in dictionary. + const String parameter_name = key.substr(strlen("param_")); + context.setQueryParameter(parameter_name, value); + } else { /// All other query parameters are treated as settings. @@ -516,7 +521,7 @@ void HTTPHandler::processQuery( std::string full_query; /// Support for "external data for query processing". - if (isExternalData) + if (has_external_data) { ExternalTablesHandler handler(context, params); params.load(request, istr, handler); diff --git a/dbms/programs/server/MetricsTransmitter.cpp b/dbms/programs/server/MetricsTransmitter.cpp index 7ceb214a518..e8cf4a2c21b 100644 --- a/dbms/programs/server/MetricsTransmitter.cpp +++ b/dbms/programs/server/MetricsTransmitter.cpp @@ -1,7 +1,6 @@ #include "MetricsTransmitter.h" #include -#include #include #include @@ -16,6 +15,17 @@ namespace DB { +MetricsTransmitter::MetricsTransmitter( + const Poco::Util::AbstractConfiguration & config, const std::string & config_name, const AsynchronousMetrics & async_metrics) + : async_metrics(async_metrics), config_name(config_name) +{ + interval_seconds = config.getInt(config_name + ".interval", 60); + send_events = config.getBool(config_name + ".events", true); + send_metrics = config.getBool(config_name + ".metrics", true); + send_asynchronous_metrics = config.getBool(config_name + ".asynchronous_metrics", true); +} + + MetricsTransmitter::~MetricsTransmitter() { try @@ -38,10 +48,7 @@ MetricsTransmitter::~MetricsTransmitter() void MetricsTransmitter::run() { - const auto & config = context.getConfigRef(); - auto interval = config.getInt(config_name + ".interval", 60); - - const std::string thread_name = "MetrTx" + std::to_string(interval); + const std::string thread_name = "MetrTx" + std::to_string(interval_seconds); setThreadName(thread_name.c_str()); const auto get_next_time = [](size_t seconds) @@ -60,7 +67,7 @@ void MetricsTransmitter::run() while (true) { - if (cond.wait_until(lock, get_next_time(interval), [this] { return quit; })) + if (cond.wait_until(lock, get_next_time(interval_seconds), [this] { return quit; })) break; transmit(prev_counters); @@ -70,14 +77,12 @@ void MetricsTransmitter::run() void MetricsTransmitter::transmit(std::vector & prev_counters) { - const auto & config = context.getConfigRef(); auto async_metrics_values = async_metrics.getValues(); GraphiteWriter::KeyValueVector key_vals{}; key_vals.reserve(ProfileEvents::end() + CurrentMetrics::end() + async_metrics_values.size()); - - if (config.getBool(config_name + ".events", true)) + if (send_events) { for (size_t i = 0, end = ProfileEvents::end(); i < end; ++i) { @@ -90,7 +95,7 @@ void MetricsTransmitter::transmit(std::vector & prev_count } } - if (config.getBool(config_name + ".metrics", true)) + if (send_metrics) { for (size_t i = 0, end = CurrentMetrics::end(); i < end; ++i) { @@ -101,7 +106,7 @@ void MetricsTransmitter::transmit(std::vector & prev_count } } - if (config.getBool(config_name + ".asynchronous_metrics", true)) + if (send_asynchronous_metrics) { for (const auto & name_value : async_metrics_values) { @@ -112,4 +117,5 @@ void MetricsTransmitter::transmit(std::vector & prev_count if (key_vals.size()) BaseDaemon::instance().writeToGraphite(key_vals, config_name); } + } diff --git a/dbms/programs/server/MetricsTransmitter.h b/dbms/programs/server/MetricsTransmitter.h index fd3853a7a9e..69a11bf2bad 100644 --- a/dbms/programs/server/MetricsTransmitter.h +++ b/dbms/programs/server/MetricsTransmitter.h @@ -9,14 +9,21 @@ #include +namespace Poco +{ + namespace Util + { + class AbstractConfiguration; + } +} + namespace DB { class AsynchronousMetrics; -class Context; -/** Automatically sends +/** Automatically sends * - difference of ProfileEvents; * - values of CurrentMetrics; * - values of AsynchronousMetrics; @@ -25,33 +32,29 @@ class Context; class MetricsTransmitter { public: - MetricsTransmitter(Context & context_, - const AsynchronousMetrics & async_metrics_, - const std::string & config_name_) - : context(context_) - , async_metrics(async_metrics_) - , config_name(config_name_) - { - } + MetricsTransmitter(const Poco::Util::AbstractConfiguration & config, const std::string & config_name, const AsynchronousMetrics & async_metrics); ~MetricsTransmitter(); private: void run(); void transmit(std::vector & prev_counters); - Context & context; - const AsynchronousMetrics & async_metrics; - const std::string config_name; + + std::string config_name; + UInt32 interval_seconds; + bool send_events; + bool send_metrics; + bool send_asynchronous_metrics; bool quit = false; std::mutex mutex; std::condition_variable cond; ThreadFromGlobalPool thread{&MetricsTransmitter::run, this}; - static constexpr auto profile_events_path_prefix = "ClickHouse.ProfileEvents."; - static constexpr auto current_metrics_path_prefix = "ClickHouse.Metrics."; - static constexpr auto asynchronous_metrics_path_prefix = "ClickHouse.AsynchronousMetrics."; + static inline constexpr auto profile_events_path_prefix = "ClickHouse.ProfileEvents."; + static inline constexpr auto current_metrics_path_prefix = "ClickHouse.Metrics."; + static inline constexpr auto asynchronous_metrics_path_prefix = "ClickHouse.AsynchronousMetrics."; }; } diff --git a/dbms/programs/server/MySQLHandler.cpp b/dbms/programs/server/MySQLHandler.cpp index a935f13e82a..f9aa29ab0b5 100644 --- a/dbms/programs/server/MySQLHandler.cpp +++ b/dbms/programs/server/MySQLHandler.cpp @@ -18,13 +18,19 @@ #include #include +#include + namespace DB { + using namespace MySQLProtocol; + + using Poco::Net::SecureStreamSocket; using Poco::Net::SSLManager; + namespace ErrorCodes { extern const int MYSQL_CLIENT_INSUFFICIENT_CAPABILITIES; @@ -48,7 +54,7 @@ MySQLHandler::MySQLHandler(IServer & server_, const Poco::Net::StreamSocket & so void MySQLHandler::run() { connection_context = server.context(); - connection_context.setSessionContext(connection_context); + connection_context.makeSessionContext(); connection_context.setDefaultFormat("MySQLWire"); in = std::make_shared(socket()); diff --git a/dbms/programs/server/MySQLHandler.h b/dbms/programs/server/MySQLHandler.h index f55906f7428..ffbaf1d4a6b 100644 --- a/dbms/programs/server/MySQLHandler.h +++ b/dbms/programs/server/MySQLHandler.h @@ -4,7 +4,6 @@ #include #include #include -#include #include "IServer.h" diff --git a/dbms/programs/server/Server.cpp b/dbms/programs/server/Server.cpp index cd25d6b4804..3d50466df84 100644 --- a/dbms/programs/server/Server.cpp +++ b/dbms/programs/server/Server.cpp @@ -187,7 +187,7 @@ int Server::main(const std::vector & /*args*/) * settings, available functions, data types, aggregate functions, databases... */ global_context = std::make_unique(Context::createGlobal()); - global_context->setGlobalContext(*global_context); + global_context->makeGlobalContext(); global_context->setApplicationType(Context::ApplicationType::SERVER); bool has_zookeeper = config().has("zookeeper"); @@ -525,18 +525,26 @@ int Server::main(const std::vector & /*args*/) } else { - /// Initialize a watcher updating DNS cache in case of network errors - dns_cache_updater = std::make_unique(*global_context); + /// Initialize a watcher periodically updating DNS cache + dns_cache_updater = std::make_unique(*global_context, config().getInt("dns_cache_update_period", 15)); } #if defined(__linux__) if (!TaskStatsInfoGetter::checkPermissions()) { LOG_INFO(log, "It looks like the process has no CAP_NET_ADMIN capability, 'taskstats' performance statistics will be disabled." - " It could happen due to incorrect ClickHouse package installation." - " You could resolve the problem manually with 'sudo setcap cap_net_admin=+ep /usr/bin/clickhouse'." - " Note that it will not work on 'nosuid' mounted filesystems." - " It also doesn't work if you run clickhouse-server inside network namespace as it happens in some containers."); + " It could happen due to incorrect ClickHouse package installation." + " You could resolve the problem manually with 'sudo setcap cap_net_admin=+ep /usr/bin/clickhouse'." + " Note that it will not work on 'nosuid' mounted filesystems." + " It also doesn't work if you run clickhouse-server inside network namespace as it happens in some containers."); + } + + if (!hasLinuxCapability(CAP_SYS_NICE)) + { + LOG_INFO(log, "It looks like the process has no CAP_SYS_NICE capability, the setting 'os_thread_nice' will have no effect." + " It could happen due to incorrect ClickHouse package installation." + " You could resolve the problem manually with 'sudo setcap cap_sys_nice=+ep /usr/bin/clickhouse'." + " Note that it will not work on 'nosuid' mounted filesystems."); } #else LOG_INFO(log, "TaskStats is not implemented for this OS. IO accounting will be disabled."); @@ -738,6 +746,7 @@ int Server::main(const std::vector & /*args*/) if (config().has("mysql_port")) { +#if USE_POCO_NETSSL Poco::Net::ServerSocket socket; auto address = socket_bind_listen(socket, listen_host, config().getInt("mysql_port"), /* secure = */ true); socket.setReceiveTimeout(Poco::Timespan()); @@ -749,6 +758,10 @@ int Server::main(const std::vector & /*args*/) new Poco::Net::TCPServerParams)); LOG_INFO(log, "Listening for MySQL compatibility protocol: " + address.toString()); +#else + throw Exception{"SSL support for MySQL protocol is disabled because Poco library was built without NetSSL support.", + ErrorCodes::SUPPORT_IS_DISABLED}; +#endif } } catch (const Poco::Exception & e) @@ -773,6 +786,8 @@ int Server::main(const std::vector & /*args*/) main_config_reloader->start(); users_config_reloader->start(); + if (dns_cache_updater) + dns_cache_updater->start(); { std::stringstream message; @@ -823,6 +838,7 @@ int Server::main(const std::vector & /*args*/) log, "Closed connections." << (current_connections ? " But " + toString(current_connections) + " remains." " Tip: To increase wait time add to config: 60" : "")); + dns_cache_updater.reset(); main_config_reloader.reset(); users_config_reloader.reset(); }); @@ -850,7 +866,7 @@ int Server::main(const std::vector & /*args*/) for (const auto & graphite_key : DB::getMultipleKeysFromConfig(config(), "", "graphite")) { metrics_transmitters.emplace_back(std::make_unique( - *global_context, async_metrics, graphite_key)); + global_context->getConfigRef(), graphite_key, async_metrics)); } SessionCleaner session_cleaner(*global_context); diff --git a/dbms/programs/server/TCPHandler.cpp b/dbms/programs/server/TCPHandler.cpp index 6ec9ec5d416..e0618b934af 100644 --- a/dbms/programs/server/TCPHandler.cpp +++ b/dbms/programs/server/TCPHandler.cpp @@ -29,6 +29,8 @@ #include #include +#include + #include "TCPHandler.h" @@ -54,7 +56,7 @@ void TCPHandler::runImpl() ThreadStatus thread_status; connection_context = server.context(); - connection_context.setSessionContext(connection_context); + connection_context.makeSessionContext(); Settings global_settings = connection_context.getSettings(); @@ -120,17 +122,26 @@ void TCPHandler::runImpl() while (1) { - /// Set context of request. - query_context = connection_context; - - /// We are waiting for a packet from the client. Thus, every `POLL_INTERVAL` seconds check whether we need to shut down. - while (!static_cast(*in).poll(global_settings.poll_interval * 1000000) && !server.isCancelled()) - ; + /// We are waiting for a packet from the client. Thus, every `poll_interval` seconds check whether we need to shut down. + { + Stopwatch idle_time; + while (!static_cast(*in).poll(global_settings.poll_interval * 1000000) && !server.isCancelled()) + { + if (idle_time.elapsedSeconds() > global_settings.idle_connection_timeout) + { + LOG_TRACE(log, "Closing idle connection"); + return; + } + } + } /// If we need to shut down, or client disconnects. if (server.isCancelled() || in->eof()) break; + /// Set context of request. + query_context = connection_context; + Stopwatch watch; state.reset(); @@ -198,6 +209,8 @@ void TCPHandler::runImpl() /// Does the request require receive data from client? if (state.need_receive_data_for_insert) processInsertQuery(global_settings); + else if (state.io.pipeline.initialized()) + processOrdinaryQueryWithProcessors(query_context->getSettingsRef().max_threads); else processOrdinaryQuery(); @@ -438,9 +451,9 @@ void TCPHandler::processOrdinaryQuery() */ if (!block && !isQueryCancelled()) { - sendTotals(); - sendExtremes(); - sendProfileInfo(); + sendTotals(state.io.in->getTotals()); + sendExtremes(state.io.in->getExtremes()); + sendProfileInfo(state.io.in->getProfileInfo()); sendProgress(); sendLogs(); } @@ -456,6 +469,129 @@ void TCPHandler::processOrdinaryQuery() state.io.onFinish(); } +void TCPHandler::processOrdinaryQueryWithProcessors(size_t num_threads) +{ + auto & pipeline = state.io.pipeline; + + /// Send header-block, to allow client to prepare output format for data to send. + { + auto & header = pipeline.getHeader(); + + if (header) + sendData(header); + } + + auto lazy_format = std::make_shared(pipeline.getHeader()); + pipeline.setOutput(lazy_format); + + { + auto thread_group = CurrentThread::getGroup(); + ThreadPool pool(1); + auto executor = pipeline.execute(); + std::atomic_bool exception = false; + + pool.schedule([&]() + { + /// ThreadStatus thread_status; + + if (thread_group) + CurrentThread::attachTo(thread_group); + + SCOPE_EXIT( + if (thread_group) + CurrentThread::detachQueryIfNotDetached(); + ); + + CurrentMetrics::Increment query_thread_metric_increment{CurrentMetrics::QueryThread}; + setThreadName("QueryPipelineEx"); + + try + { + executor->execute(num_threads); + } + catch (...) + { + exception = true; + throw; + } + }); + + /// Wait in case of exception. Delete pipeline to release memory. + SCOPE_EXIT( + /// Clear queue in case if somebody is waiting lazy_format to push. + lazy_format->finish(); + lazy_format->clearQueue(); + + pool.wait(); + pipeline = QueryPipeline() + ); + + while (true) + { + Block block; + + while (true) + { + if (isQueryCancelled()) + { + /// A packet was received requesting to stop execution of the request. + executor->cancel(); + + break; + } + else + { + if (after_send_progress.elapsed() / 1000 >= query_context->getSettingsRef().interactive_delay) + { + /// Some time passed and there is a progress. + after_send_progress.restart(); + sendProgress(); + } + + sendLogs(); + + if ((block = lazy_format->getBlock(query_context->getSettingsRef().interactive_delay / 1000))) + break; + + if (lazy_format->isFinished()) + break; + + if (exception) + { + pool.wait(); + break; + } + } + } + + /** If data has run out, we will send the profiling data and total values to + * the last zero block to be able to use + * this information in the suffix output of stream. + * If the request was interrupted, then `sendTotals` and other methods could not be called, + * because we have not read all the data yet, + * and there could be ongoing calculations in other threads at the same time. + */ + if (!block && !isQueryCancelled()) + { + pool.wait(); + pipeline.finalize(); + + sendTotals(lazy_format->getTotals()); + sendExtremes(lazy_format->getExtremes()); + sendProfileInfo(lazy_format->getProfileInfo()); + sendProgress(); + sendLogs(); + } + + sendData(block); + if (!block) + break; + } + } + + state.io.onFinish(); +} + void TCPHandler::processTablesStatusRequest() { @@ -486,18 +622,16 @@ void TCPHandler::processTablesStatusRequest() } -void TCPHandler::sendProfileInfo() +void TCPHandler::sendProfileInfo(const BlockStreamProfileInfo & info) { writeVarUInt(Protocol::Server::ProfileInfo, *out); - state.io.in->getProfileInfo().write(*out); + info.write(*out); out->next(); } -void TCPHandler::sendTotals() +void TCPHandler::sendTotals(const Block & totals) { - const Block & totals = state.io.in->getTotals(); - if (totals) { initBlockOutput(totals); @@ -512,10 +646,8 @@ void TCPHandler::sendTotals() } -void TCPHandler::sendExtremes() +void TCPHandler::sendExtremes(const Block & extremes) { - Block extremes = state.io.in->getExtremes(); - if (extremes) { initBlockOutput(extremes); @@ -721,7 +853,7 @@ bool TCPHandler::receiveData() if (!(storage = query_context->tryGetExternalTable(external_table_name))) { NamesAndTypesList columns = block.getNamesAndTypesList(); - storage = StorageMemory::create(external_table_name, ColumnsDescription{columns}); + storage = StorageMemory::create("_external", external_table_name, ColumnsDescription{columns}); storage->startup(); query_context->addExternalTable(external_table_name, storage); } diff --git a/dbms/programs/server/TCPHandler.h b/dbms/programs/server/TCPHandler.h index a2febf20a20..3cacd5fae95 100644 --- a/dbms/programs/server/TCPHandler.h +++ b/dbms/programs/server/TCPHandler.h @@ -36,6 +36,12 @@ struct QueryState QueryProcessingStage::Enum stage = QueryProcessingStage::Complete; Protocol::Compression compression = Protocol::Compression::Disable; + /// A queue with internal logs that will be passed to client. It must be + /// destroyed after input/output blocks, because they may contain other + /// threads that use this queue. + InternalTextLogsQueuePtr logs_queue; + BlockOutputStreamPtr logs_block_out; + /// From where to read data for INSERT. std::shared_ptr maybe_compressed_in; BlockInputStreamPtr block_in; @@ -64,10 +70,6 @@ struct QueryState /// Timeouts setter for current query std::unique_ptr timeout_setter; - /// A queue with internal logs that will be passed to client - InternalTextLogsQueuePtr logs_queue; - BlockOutputStreamPtr logs_block_out; - void reset() { *this = QueryState(); @@ -143,6 +145,8 @@ private: /// Process a request that does not require the receiving of data blocks from the client void processOrdinaryQuery(); + void processOrdinaryQueryWithProcessors(size_t num_threads); + void processTablesStatusRequest(); void sendHello(); @@ -153,9 +157,9 @@ private: void sendProgress(); void sendLogs(); void sendEndOfStream(); - void sendProfileInfo(); - void sendTotals(); - void sendExtremes(); + void sendProfileInfo(const BlockStreamProfileInfo & info); + void sendTotals(const Block & totals); + void sendExtremes(const Block & extremes); /// Creates state.block_in/block_out for blocks read/write, depending on whether compression is enabled. void initBlockInput(); diff --git a/dbms/src/AggregateFunctions/AggregateFunctionForEach.h b/dbms/src/AggregateFunctions/AggregateFunctionForEach.h index 39a52a7fa6e..5b095d1825f 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionForEach.h +++ b/dbms/src/AggregateFunctions/AggregateFunctionForEach.h @@ -53,42 +53,49 @@ private: { AggregateFunctionForEachData & state = data(place); - /// Ensure we have aggreate states for new_size elements, allocate from arena if needed - + /// Ensure we have aggreate states for new_size elements, allocate + /// from arena if needed. When reallocating, we can't copy the + /// states to new buffer with memcpy, because they may contain pointers + /// to themselves. In particular, this happens when a state contains + /// a PODArrayWithStackMemory, which stores small number of elements + /// inline. This is why we create new empty states in the new buffer, + /// and merge the old states to them. size_t old_size = state.dynamic_array_size; if (old_size < new_size) { - state.array_of_aggregate_datas = arena.alignedRealloc( - state.array_of_aggregate_datas, - old_size * nested_size_of_data, + char * old_state = state.array_of_aggregate_datas; + char * new_state = arena.alignedAlloc( new_size * nested_size_of_data, nested_func->alignOfData()); - size_t i = old_size; - char * nested_state = state.array_of_aggregate_datas + i * nested_size_of_data; - + size_t i; try { - for (; i < new_size; ++i) + for (i = 0; i < new_size; ++i) { - nested_func->create(nested_state); - nested_state += nested_size_of_data; + nested_func->create(&new_state[i * nested_size_of_data]); } } catch (...) { size_t cleanup_size = i; - nested_state = state.array_of_aggregate_datas + i * nested_size_of_data; for (i = 0; i < cleanup_size; ++i) { - nested_func->destroy(nested_state); - nested_state += nested_size_of_data; + nested_func->destroy(&new_state[i * nested_size_of_data]); } throw; } + for (i = 0; i < old_size; i++) + { + nested_func->merge(&new_state[i * nested_size_of_data], + &old_state[i * nested_size_of_data], + &arena); + } + + state.array_of_aggregate_datas = new_state; state.dynamic_array_size = new_size; } diff --git a/dbms/src/AggregateFunctions/AggregateFunctionQuantile.h b/dbms/src/AggregateFunctions/AggregateFunctionQuantile.h index 0748955f9ef..2e9ec914b99 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionQuantile.h +++ b/dbms/src/AggregateFunctions/AggregateFunctionQuantile.h @@ -82,14 +82,6 @@ public: { if (!returns_many && levels.size() > 1) throw Exception("Aggregate function " + getName() + " require one parameter or less", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); - - if constexpr (std::is_same_v>) - { - /// QuantileTiming only supports integers (it works only for unsigned integers but signed are also accepted for convenience). - if (!isInteger(argument_type)) - throw Exception("Argument for function " + std::string(Name::name) + " must be integer, but it has type " - + argument_type->getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); - } } String getName() const override { return Name::name; } @@ -111,16 +103,21 @@ public: void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena *) const override { - /// Out of range conversion may occur. This is Ok. + auto value = static_cast(*columns[0]).getData()[row_num]; - const auto & column = static_cast(*columns[0]); + if constexpr (std::is_same_v>) + { + /// QuantileTiming only supports integers. + if (isNaN(value) || value > std::numeric_limits::max() || value < std::numeric_limits::min()) + return; + } if constexpr (has_second_arg) this->data(place).add( - column.getData()[row_num], + value, columns[1]->getUInt(row_num)); else - this->data(place).add(column.getData()[row_num]); + this->data(place).add(value); } void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override diff --git a/dbms/src/AggregateFunctions/AggregateFunctionSequenceMatch.h b/dbms/src/AggregateFunctions/AggregateFunctionSequenceMatch.h index 017b6d113dc..80860fdb62a 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionSequenceMatch.h +++ b/dbms/src/AggregateFunctions/AggregateFunctionSequenceMatch.h @@ -47,8 +47,7 @@ struct AggregateFunctionSequenceMatchData final using Comparator = ComparePairFirst; bool sorted = true; - static constexpr size_t bytes_in_arena = 64; - PODArray, bytes_in_arena>> events_list; + PODArrayWithStackMemory events_list; void add(const Timestamp timestamp, const Events & events) { @@ -203,8 +202,7 @@ private: PatternAction(const PatternActionType type, const std::uint64_t extra = 0) : type{type}, extra{extra} {} }; - static constexpr size_t bytes_on_stack = 64; - using PatternActions = PODArray, bytes_on_stack>>; + using PatternActions = PODArrayWithStackMemory; Derived & derived() { return static_cast(*this); } diff --git a/dbms/src/AggregateFunctions/AggregateFunctionTimeSeriesGroupSum.h b/dbms/src/AggregateFunctions/AggregateFunctionTimeSeriesGroupSum.h index c74ad8c0bdb..5e2a9b15f4e 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionTimeSeriesGroupSum.h +++ b/dbms/src/AggregateFunctions/AggregateFunctionTimeSeriesGroupSum.h @@ -68,9 +68,8 @@ struct AggregateFunctionTimeSeriesGroupSumData } }; - static constexpr size_t bytes_on_stack = 128; typedef std::map Series; - typedef PODArray, bytes_on_stack>> AggSeries; + typedef PODArrayWithStackMemory AggSeries; Series ss; AggSeries result; diff --git a/dbms/src/AggregateFunctions/AggregateFunctionWindowFunnel.h b/dbms/src/AggregateFunctions/AggregateFunctionWindowFunnel.h index 9a738d3fefb..1e3c005f73f 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionWindowFunnel.h +++ b/dbms/src/AggregateFunctions/AggregateFunctionWindowFunnel.h @@ -35,10 +35,7 @@ template struct AggregateFunctionWindowFunnelData { using TimestampEvent = std::pair; - - static constexpr size_t bytes_on_stack = 64; - using TimestampEvents = PODArray, bytes_on_stack>>; - + using TimestampEvents = PODArray; using Comparator = ComparePairFirst; bool sorted = true; diff --git a/dbms/src/AggregateFunctions/QuantileExact.h b/dbms/src/AggregateFunctions/QuantileExact.h index b4398e8bb7f..a5b616669b9 100644 --- a/dbms/src/AggregateFunctions/QuantileExact.h +++ b/dbms/src/AggregateFunctions/QuantileExact.h @@ -27,8 +27,7 @@ struct QuantileExact { /// The memory will be allocated to several elements at once, so that the state occupies 64 bytes. static constexpr size_t bytes_in_arena = 64 - sizeof(PODArray); - - using Array = PODArray, bytes_in_arena>>; + using Array = PODArrayWithStackMemory; Array array; void add(const Value & x) diff --git a/dbms/src/AggregateFunctions/QuantileTDigest.h b/dbms/src/AggregateFunctions/QuantileTDigest.h index e9f261d4c21..f7201ef3b0d 100644 --- a/dbms/src/AggregateFunctions/QuantileTDigest.h +++ b/dbms/src/AggregateFunctions/QuantileTDigest.h @@ -86,8 +86,7 @@ class QuantileTDigest /// The memory will be allocated to several elements at once, so that the state occupies 64 bytes. static constexpr size_t bytes_in_arena = 128 - sizeof(PODArray) - sizeof(Count) - sizeof(UInt32); - - using Summary = PODArray, bytes_in_arena>>; + using Summary = PODArrayWithStackMemory; Summary summary; Count count = 0; diff --git a/dbms/src/AggregateFunctions/ReservoirSampler.h b/dbms/src/AggregateFunctions/ReservoirSampler.h index ad5bf10f48f..30d72709ac2 100644 --- a/dbms/src/AggregateFunctions/ReservoirSampler.h +++ b/dbms/src/AggregateFunctions/ReservoirSampler.h @@ -194,8 +194,7 @@ private: friend void rs_perf_test(); /// We allocate a little memory on the stack - to avoid allocations when there are many objects with a small number of elements. - static constexpr size_t bytes_on_stack = 64; - using Array = DB::PODArray, bytes_on_stack>>; + using Array = DB::PODArrayWithStackMemory; size_t sample_count; size_t total_values = 0; diff --git a/dbms/src/AggregateFunctions/ReservoirSamplerDeterministic.h b/dbms/src/AggregateFunctions/ReservoirSamplerDeterministic.h index c543e662b2a..4beeecd93bc 100644 --- a/dbms/src/AggregateFunctions/ReservoirSamplerDeterministic.h +++ b/dbms/src/AggregateFunctions/ReservoirSamplerDeterministic.h @@ -164,9 +164,8 @@ public: private: /// We allocate some memory on the stack to avoid allocations when there are many objects with a small number of elements. - static constexpr size_t bytes_on_stack = 64; using Element = std::pair; - using Array = DB::PODArray, bytes_on_stack>>; + using Array = DB::PODArray; size_t sample_count; size_t total_values{}; diff --git a/dbms/src/CMakeLists.txt b/dbms/src/CMakeLists.txt index c5b661b5912..84755f7f280 100644 --- a/dbms/src/CMakeLists.txt +++ b/dbms/src/CMakeLists.txt @@ -12,5 +12,6 @@ add_subdirectory (Interpreters) add_subdirectory (AggregateFunctions) add_subdirectory (Client) add_subdirectory (TableFunctions) +add_subdirectory (Processors) add_subdirectory (Formats) add_subdirectory (Compression) diff --git a/dbms/src/Client/Connection.cpp b/dbms/src/Client/Connection.cpp index 9651ef54e1b..9cdda9fdf0d 100644 --- a/dbms/src/Client/Connection.cpp +++ b/dbms/src/Client/Connection.cpp @@ -73,7 +73,7 @@ void Connection::connect(const ConnectionTimeouts & timeouts) current_resolved_address = DNSResolver::instance().resolveAddress(host, port); - socket->connect(current_resolved_address, timeouts.connection_timeout); + socket->connect(*current_resolved_address, timeouts.connection_timeout); socket->setReceiveTimeout(timeouts.receive_timeout); socket->setSendTimeout(timeouts.send_timeout); socket->setNoDelay(true); @@ -533,12 +533,9 @@ void Connection::sendExternalTablesData(ExternalTablesData & data) LOG_DEBUG(log_wrapper.get(), msg.rdbuf()); } -Poco::Net::SocketAddress Connection::getResolvedAddress() const +std::optional Connection::getResolvedAddress() const { - if (connected) - return current_resolved_address; - - return DNSResolver::instance().resolveAddress(host, port); + return current_resolved_address; } @@ -595,7 +592,9 @@ Connection::Packet Connection::receivePacket() switch (res.type) { - case Protocol::Server::Data: + case Protocol::Server::Data: [[fallthrough]]; + case Protocol::Server::Totals: [[fallthrough]]; + case Protocol::Server::Extremes: res.block = receiveData(); return res; @@ -611,16 +610,6 @@ Connection::Packet Connection::receivePacket() res.profile_info = receiveProfileInfo(); return res; - case Protocol::Server::Totals: - /// Block with total values is passed in same form as ordinary block. The only difference is packed id. - res.block = receiveData(); - return res; - - case Protocol::Server::Extremes: - /// Same as above. - res.block = receiveData(); - return res; - case Protocol::Server::Log: res.block = receiveLogData(); return res; @@ -720,11 +709,14 @@ void Connection::initBlockLogsInput() void Connection::setDescription() { auto resolved_address = getResolvedAddress(); - description = host + ":" + toString(resolved_address.port()); - auto ip_address = resolved_address.host().toString(); + description = host + ":" + toString(port); - if (host != ip_address) - description += ", " + ip_address; + if (resolved_address) + { + auto ip_address = resolved_address->host().toString(); + if (host != ip_address) + description += ", " + ip_address; + } } diff --git a/dbms/src/Client/Connection.h b/dbms/src/Client/Connection.h index 2338e4c8965..03a771c257f 100644 --- a/dbms/src/Client/Connection.h +++ b/dbms/src/Client/Connection.h @@ -63,7 +63,7 @@ public: Poco::Timespan sync_request_timeout_ = Poco::Timespan(DBMS_DEFAULT_SYNC_REQUEST_TIMEOUT_SEC, 0)) : host(host_), port(port_), default_database(default_database_), - user(user_), password(password_), current_resolved_address(host, port), + user(user_), password(password_), client_name(client_name_), compression(compression_), secure(secure_), @@ -168,9 +168,6 @@ public: size_t outBytesCount() const { return out ? out->count() : 0; } size_t inBytesCount() const { return in ? in->count() : 0; } - /// Returns initially resolved address - Poco::Net::SocketAddress getResolvedAddress() const; - private: String host; UInt16 port; @@ -180,12 +177,15 @@ private: /// Address is resolved during the first connection (or the following reconnects) /// Use it only for logging purposes - Poco::Net::SocketAddress current_resolved_address; + std::optional current_resolved_address; /// For messages in log and in exceptions. String description; void setDescription(); + /// Returns resolved address if it was resolved. + std::optional getResolvedAddress() const; + String client_name; bool connected = false; diff --git a/dbms/src/Columns/Collator.cpp b/dbms/src/Columns/Collator.cpp index 3232893ee15..3c4eceddeb6 100644 --- a/dbms/src/Columns/Collator.cpp +++ b/dbms/src/Columns/Collator.cpp @@ -6,9 +6,9 @@ #include #else #ifdef __clang__ - #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-private-field" #endif + #pragma clang diagnostic ignored "-Wmissing-noreturn" #endif #include @@ -26,7 +26,6 @@ namespace DB } } - Collator::Collator(const std::string & locale_) : locale(Poco::toLower(locale_)) { #if USE_ICU diff --git a/dbms/src/Columns/ColumnConst.h b/dbms/src/Columns/ColumnConst.h index 05a9562e549..6731061a797 100644 --- a/dbms/src/Columns/ColumnConst.h +++ b/dbms/src/Columns/ColumnConst.h @@ -99,6 +99,11 @@ public: return data->getBool(0); } + Float64 getFloat64(size_t) const override + { + return data->getFloat64(0); + } + bool isNullAt(size_t) const override { return data->isNullAt(0); @@ -197,8 +202,8 @@ public: return false; } + bool isNullable() const override { return isColumnNullable(*data); } bool onlyNull() const override { return data->isNullAt(0); } - bool isColumnConst() const override { return true; } bool isNumeric() const override { return data->isNumeric(); } bool isFixedAndContiguous() const override { return data->isFixedAndContiguous(); } bool valuesHaveFixedSize() const override { return data->valuesHaveFixedSize(); } diff --git a/dbms/src/Columns/ColumnLowCardinality.h b/dbms/src/Columns/ColumnLowCardinality.h index d36b91b0c40..fc96fc97550 100644 --- a/dbms/src/Columns/ColumnLowCardinality.h +++ b/dbms/src/Columns/ColumnLowCardinality.h @@ -57,6 +57,8 @@ public: UInt64 get64(size_t n) const override { return getDictionary().get64(getIndexes().getUInt(n)); } UInt64 getUInt(size_t n) const override { return getDictionary().getUInt(getIndexes().getUInt(n)); } Int64 getInt(size_t n) const override { return getDictionary().getInt(getIndexes().getUInt(n)); } + Float64 getFloat64(size_t n) const override { return getDictionary().getInt(getIndexes().getFloat64(n)); } + bool getBool(size_t n) const override { return getDictionary().getInt(getIndexes().getBool(n)); } bool isNullAt(size_t n) const override { return getDictionary().isNullAt(getIndexes().getUInt(n)); } ColumnPtr cut(size_t start, size_t length) const override { @@ -146,6 +148,7 @@ public: size_t sizeOfValueIfFixed() const override { return getDictionary().sizeOfValueIfFixed(); } bool isNumeric() const override { return getDictionary().isNumeric(); } bool lowCardinality() const override { return true; } + bool isNullable() const override { return isColumnNullable(*dictionary.getColumnUniquePtr()); } const IColumnUnique & getDictionary() const { return dictionary.getColumnUnique(); } const ColumnPtr & getDictionaryPtr() const { return dictionary.getColumnUniquePtr(); } diff --git a/dbms/src/Columns/ColumnNullable.cpp b/dbms/src/Columns/ColumnNullable.cpp index 20511ec6bfc..3ae692552e8 100644 --- a/dbms/src/Columns/ColumnNullable.cpp +++ b/dbms/src/Columns/ColumnNullable.cpp @@ -27,7 +27,7 @@ ColumnNullable::ColumnNullable(MutableColumnPtr && nested_column_, MutableColumn if (!getNestedColumn().canBeInsideNullable()) throw Exception{getNestedColumn().getName() + " cannot be inside Nullable column", ErrorCodes::ILLEGAL_COLUMN}; - if (null_map->isColumnConst()) + if (isColumnConst(*null_map)) throw Exception{"ColumnNullable cannot have constant null map", ErrorCodes::ILLEGAL_COLUMN}; } @@ -451,13 +451,12 @@ void ColumnNullable::checkConsistency() const ErrorCodes::SIZES_OF_NESTED_COLUMNS_ARE_INCONSISTENT); } - ColumnPtr makeNullable(const ColumnPtr & column) { - if (column->isColumnNullable()) + if (isColumnNullable(*column)) return column; - if (column->isColumnConst()) + if (isColumnConst(*column)) return ColumnConst::create(makeNullable(static_cast(*column).getDataColumnPtr()), column->size()); return ColumnNullable::create(column, ColumnUInt8::create(column->size(), 0)); diff --git a/dbms/src/Columns/ColumnNullable.h b/dbms/src/Columns/ColumnNullable.h index 19246cd597d..b4db692b61d 100644 --- a/dbms/src/Columns/ColumnNullable.h +++ b/dbms/src/Columns/ColumnNullable.h @@ -100,7 +100,7 @@ public: return false; } - bool isColumnNullable() const override { return true; } + bool isNullable() const override { return true; } bool isFixedAndContiguous() const override { return false; } bool valuesHaveFixedSize() const override { return nested_column->valuesHaveFixedSize(); } size_t sizeOfValueIfFixed() const override { return null_map->sizeOfValueIfFixed() + nested_column->sizeOfValueIfFixed(); } @@ -142,7 +142,6 @@ private: void applyNullMapImpl(const ColumnUInt8 & map); }; - ColumnPtr makeNullable(const ColumnPtr & column); } diff --git a/dbms/src/Columns/ColumnTuple.cpp b/dbms/src/Columns/ColumnTuple.cpp index c5a14f497dd..f7a95c1ac9f 100644 --- a/dbms/src/Columns/ColumnTuple.cpp +++ b/dbms/src/Columns/ColumnTuple.cpp @@ -39,7 +39,7 @@ ColumnTuple::ColumnTuple(MutableColumns && mutable_columns) columns.reserve(mutable_columns.size()); for (auto & column : mutable_columns) { - if (column->isColumnConst()) + if (isColumnConst(*column)) throw Exception{"ColumnTuple cannot have ColumnConst as its element", ErrorCodes::ILLEGAL_COLUMN}; columns.push_back(std::move(column)); @@ -49,7 +49,7 @@ ColumnTuple::ColumnTuple(MutableColumns && mutable_columns) ColumnTuple::Ptr ColumnTuple::create(const Columns & columns) { for (const auto & column : columns) - if (column->isColumnConst()) + if (isColumnConst(*column)) throw Exception{"ColumnTuple cannot have ColumnConst as its element", ErrorCodes::ILLEGAL_COLUMN}; auto column_tuple = ColumnTuple::create(MutableColumns()); @@ -61,7 +61,7 @@ ColumnTuple::Ptr ColumnTuple::create(const Columns & columns) ColumnTuple::Ptr ColumnTuple::create(const TupleColumns & columns) { for (const auto & column : columns) - if (column->isColumnConst()) + if (isColumnConst(*column)) throw Exception{"ColumnTuple cannot have ColumnConst as its element", ErrorCodes::ILLEGAL_COLUMN}; auto column_tuple = ColumnTuple::create(MutableColumns()); diff --git a/dbms/src/Columns/ColumnUnique.h b/dbms/src/Columns/ColumnUnique.h index 11344a23a1f..febdeaafa95 100644 --- a/dbms/src/Columns/ColumnUnique.h +++ b/dbms/src/Columns/ColumnUnique.h @@ -64,6 +64,8 @@ public: UInt64 get64(size_t n) const override { return getNestedColumn()->get64(n); } UInt64 getUInt(size_t n) const override { return getNestedColumn()->getUInt(n); } Int64 getInt(size_t n) const override { return getNestedColumn()->getInt(n); } + Float64 getFloat64(size_t n) const override { return getNestedColumn()->getFloat64(n); } + bool getBool(size_t n) const override { return getNestedColumn()->getBool(n); } bool isNullAt(size_t n) const override { return is_nullable && n == getNullValueIndex(); } StringRef serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const override; void updateHashWithValue(size_t n, SipHash & hash_func) const override @@ -191,7 +193,7 @@ ColumnUnique::ColumnUnique(MutableColumnPtr && holder, bool is_nulla { if (column_holder->size() < numSpecialValues()) throw Exception("Too small holder column for ColumnUnique.", ErrorCodes::ILLEGAL_COLUMN); - if (column_holder->isColumnNullable()) + if (isColumnNullable(*column_holder)) throw Exception("Holder column for ColumnUnique can't be nullable.", ErrorCodes::ILLEGAL_COLUMN); index.setColumn(getRawColumnPtr()); @@ -271,7 +273,7 @@ size_t ColumnUnique::uniqueInsertFrom(const IColumn & src, size_t n) if (is_nullable && src.isNullAt(n)) return getNullValueIndex(); - if (auto * nullable = typeid_cast(&src)) + if (auto * nullable = checkAndGetColumn(src)) return uniqueInsertFrom(nullable->getNestedColumn(), n); auto ref = src.getDataAt(n); @@ -430,7 +432,7 @@ MutableColumnPtr ColumnUnique::uniqueInsertRangeImpl( return nullptr; }; - if (auto nullable_column = typeid_cast(&src)) + if (auto * nullable_column = checkAndGetColumn(src)) { src_column = typeid_cast(&nullable_column->getNestedColumn()); null_map = &nullable_column->getNullMapData(); diff --git a/dbms/src/Columns/ColumnVector.cpp b/dbms/src/Columns/ColumnVector.cpp index 6db110ef02e..a2d6de9df80 100644 --- a/dbms/src/Columns/ColumnVector.cpp +++ b/dbms/src/Columns/ColumnVector.cpp @@ -33,7 +33,7 @@ template StringRef ColumnVector::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const { auto pos = arena.allocContinue(sizeof(T), begin); - unalignedStore(pos, data[n]); + unalignedStore(pos, data[n]); return StringRef(pos, sizeof(T)); } diff --git a/dbms/src/Columns/FilterDescription.cpp b/dbms/src/Columns/FilterDescription.cpp index 97b123e5ee2..405ed974c6c 100644 --- a/dbms/src/Columns/FilterDescription.cpp +++ b/dbms/src/Columns/FilterDescription.cpp @@ -23,14 +23,14 @@ ConstantFilterDescription::ConstantFilterDescription(const IColumn & column) return; } - if (column.isColumnConst()) + if (isColumnConst(column)) { const ColumnConst & column_const = static_cast(column); ColumnPtr column_nested = column_const.getDataColumnPtr()->convertToFullColumnIfLowCardinality(); if (!typeid_cast(column_nested.get())) { - const ColumnNullable * column_nested_nullable = typeid_cast(column_nested.get()); + const ColumnNullable * column_nested_nullable = checkAndGetColumn(*column_nested); if (!column_nested_nullable || !typeid_cast(&column_nested_nullable->getNestedColumn())) { throw Exception("Illegal type " + column_nested->getName() + " of column for constant filter. Must be UInt8 or Nullable(UInt8).", @@ -60,7 +60,7 @@ FilterDescription::FilterDescription(const IColumn & column_) return; } - if (const ColumnNullable * nullable_column = typeid_cast(&column)) + if (auto * nullable_column = checkAndGetColumn(column)) { ColumnPtr nested_column = nullable_column->getNestedColumnPtr(); MutableColumnPtr mutable_holder = (*std::move(nested_column)).mutate(); diff --git a/dbms/src/Columns/IColumn.cpp b/dbms/src/Columns/IColumn.cpp index 43b0b25f375..cb6f7e9edf3 100644 --- a/dbms/src/Columns/IColumn.cpp +++ b/dbms/src/Columns/IColumn.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include namespace DB @@ -22,4 +24,14 @@ String IColumn::dumpStructure() const return res.str(); } +bool isColumnNullable(const IColumn & column) +{ + return checkColumn(column); +} + +bool isColumnConst(const IColumn & column) +{ + return checkColumn(column); +} + } diff --git a/dbms/src/Columns/IColumn.h b/dbms/src/Columns/IColumn.h index ffab4ff781e..3955ed4b528 100644 --- a/dbms/src/Columns/IColumn.h +++ b/dbms/src/Columns/IColumn.h @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -296,12 +297,8 @@ public: /// Various properties on behaviour of column type. - /// Is this column a container for Nullable values? It's true only for ColumnNullable. - /// Note that ColumnConst(ColumnNullable(...)) is not considered. - virtual bool isColumnNullable() const { return false; } - - /// Column stores a constant value. It's true only for ColumnConst wrapper. - virtual bool isColumnConst() const { return false; } + /// True if column contains something nullable inside. It's true for ColumnNullable, can be true or false for ColumnConst, etc. + virtual bool isNullable() const { return false; } /// It's a special kind of column, that contain single value, but is not a ColumnConst. virtual bool isDummy() const { return false; } @@ -410,4 +407,35 @@ struct IsMutableColumns template <> struct IsMutableColumns<> { static const bool value = true; }; + +template +const Type * checkAndGetColumn(const IColumn & column) +{ + return typeid_cast(&column); +} + +template +const Type * checkAndGetColumn(const IColumn * column) +{ + return typeid_cast(column); +} + +template +bool checkColumn(const IColumn & column) +{ + return checkAndGetColumn(&column); +} + +template +bool checkColumn(const IColumn * column) +{ + return checkAndGetColumn(column); +} + +/// True if column's an ColumnConst instance. It's just a syntax sugar for type check. +bool isColumnConst(const IColumn & column); + +/// True if column's an ColumnNullable instance. It's just a syntax sugar for type check. +bool isColumnNullable(const IColumn & column); + } diff --git a/dbms/src/Columns/getLeastSuperColumn.cpp b/dbms/src/Columns/getLeastSuperColumn.cpp index ddcdce6b8b2..d442c926b23 100644 --- a/dbms/src/Columns/getLeastSuperColumn.cpp +++ b/dbms/src/Columns/getLeastSuperColumn.cpp @@ -31,7 +31,7 @@ ColumnWithTypeAndName getLeastSuperColumn(std::vectortype; - if (columns[i]->column->isColumnConst()) + if (isColumnConst(*columns[i]->column)) ++num_const; } diff --git a/dbms/src/Columns/tests/CMakeLists.txt b/dbms/src/Columns/tests/CMakeLists.txt index 302c554a1fd..e69de29bb2d 100644 --- a/dbms/src/Columns/tests/CMakeLists.txt +++ b/dbms/src/Columns/tests/CMakeLists.txt @@ -1,4 +0,0 @@ -if(USE_GTEST) - add_executable(column_unique column_unique.cpp) - target_link_libraries(column_unique PRIVATE dbms ${GTEST_BOTH_LIBRARIES}) -endif() \ No newline at end of file diff --git a/dbms/src/Columns/tests/column_unique.cpp b/dbms/src/Columns/tests/gtest_column_unique.cpp similarity index 97% rename from dbms/src/Columns/tests/column_unique.cpp rename to dbms/src/Columns/tests/gtest_column_unique.cpp index 68b9367ee86..1d5ea5b4080 100644 --- a/dbms/src/Columns/tests/column_unique.cpp +++ b/dbms/src/Columns/tests/gtest_column_unique.cpp @@ -7,12 +7,6 @@ #include #include -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" -#pragma clang diagnostic ignored "-Wundef" -#endif - #include #include diff --git a/dbms/src/Common/Allocator.h b/dbms/src/Common/Allocator.h index 8b0a4b86a69..abaa5927e3d 100644 --- a/dbms/src/Common/Allocator.h +++ b/dbms/src/Common/Allocator.h @@ -255,6 +255,14 @@ private: char stack_memory[N]; public: + /// Do not use boost::noncopyable to avoid the warning about direct base + /// being inaccessible due to ambiguity, when derived classes are also + /// noncopiable (-Winaccessible-base). + AllocatorWithStackMemory(const AllocatorWithStackMemory&) = delete; + AllocatorWithStackMemory & operator = (const AllocatorWithStackMemory&) = delete; + AllocatorWithStackMemory() = default; + ~AllocatorWithStackMemory() = default; + void * alloc(size_t size) { if (size <= N) diff --git a/dbms/src/Common/Arena.h b/dbms/src/Common/Arena.h index e8e84a1e084..05154f56c19 100644 --- a/dbms/src/Common/Arena.h +++ b/dbms/src/Common/Arena.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -53,10 +54,18 @@ private: pos = begin; end = begin + size_ - pad_right; prev = prev_; + + ASAN_POISON_MEMORY_REGION(begin, size_); } ~Chunk() { + /// We must unpoison the memory before returning to the allocator, + /// because the allocator might not have asan integration, and the + /// memory would stay poisoned forever. If the allocator supports + /// asan, it will correctly poison the memory by itself. + ASAN_UNPOISON_MEMORY_REGION(begin, size()); + Allocator::free(begin, size()); if (prev) @@ -126,6 +135,7 @@ public: char * res = head->pos; head->pos += size; + ASAN_UNPOISON_MEMORY_REGION(res, size + pad_right); return res; } @@ -142,6 +152,7 @@ public: { head->pos = static_cast(head_pos); head->pos += size; + ASAN_UNPOISON_MEMORY_REGION(res, size + pad_right); return res; } @@ -161,6 +172,7 @@ public: void rollback(size_t size) { head->pos -= size; + ASAN_POISON_MEMORY_REGION(head->pos, size + pad_right); } /** Begin or expand allocation of contiguous piece of memory without alignment. @@ -187,6 +199,7 @@ public: if (!begin) begin = res; + ASAN_UNPOISON_MEMORY_REGION(res, size + pad_right); return res; } @@ -218,6 +231,8 @@ public: if (!begin) begin = res; + + ASAN_UNPOISON_MEMORY_REGION(res, size + pad_right); return res; } @@ -226,7 +241,10 @@ public: { char * res = alloc(new_size); if (old_data) + { memcpy(res, old_data, old_size); + ASAN_POISON_MEMORY_REGION(old_data, old_size); + } return res; } @@ -234,7 +252,10 @@ public: { char * res = alignedAlloc(new_size, alignment); if (old_data) + { memcpy(res, old_data, old_size); + ASAN_POISON_MEMORY_REGION(old_data, old_size); + } return res; } diff --git a/dbms/src/Common/ArenaWithFreeLists.h b/dbms/src/Common/ArenaWithFreeLists.h index 0fb0d47f8c1..2f1f0ddfb0b 100644 --- a/dbms/src/Common/ArenaWithFreeLists.h +++ b/dbms/src/Common/ArenaWithFreeLists.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -63,7 +64,13 @@ public: /// If there is a free block. if (auto & free_block_ptr = free_lists[list_idx]) { - /// Let's take it. And change the head of the list to the next item in the list. + /// Let's take it. And change the head of the list to the next + /// item in the list. We poisoned the free block before putting + /// it into the free list, so we have to unpoison it before + /// reading anything. + ASAN_UNPOISON_MEMORY_REGION(free_block_ptr, + std::max(size, sizeof(Block))); + const auto res = free_block_ptr->data; free_block_ptr = free_block_ptr->next; return res; @@ -86,6 +93,14 @@ public: const auto old_head = free_block_ptr; free_block_ptr = reinterpret_cast(ptr); free_block_ptr->next = old_head; + + /// The requested size may be less than the size of the block, but + /// we still want to poison the entire block. + /// Strictly speaking, the free blocks must be unpoisoned in + /// destructor, to support an underlying allocator that doesn't + /// integrate with asan. We don't do that, and rely on the fact that + /// our underlying allocator is Arena, which does have asan integration. + ASAN_POISON_MEMORY_REGION(ptr, 1ULL << (list_idx + 1)); } /// Size of the allocated pool in bytes diff --git a/dbms/src/Common/ColumnsHashingImpl.h b/dbms/src/Common/ColumnsHashingImpl.h index 1f826640899..d7e9010862e 100644 --- a/dbms/src/Common/ColumnsHashingImpl.h +++ b/dbms/src/Common/ColumnsHashingImpl.h @@ -279,11 +279,10 @@ protected: for (const auto & col : key_columns) { - if (col->isColumnNullable()) + if (auto * nullable_col = checkAndGetColumn(col)) { - const auto & nullable_col = static_cast(*col); - actual_columns.push_back(&nullable_col.getNestedColumn()); - null_maps.push_back(&nullable_col.getNullMapColumn()); + actual_columns.push_back(&nullable_col->getNestedColumn()); + null_maps.push_back(&nullable_col->getNullMapColumn()); } else { diff --git a/dbms/src/Common/CpuId.h b/dbms/src/Common/CpuId.h index 1bae7407818..808502ba086 100644 --- a/dbms/src/Common/CpuId.h +++ b/dbms/src/Common/CpuId.h @@ -14,8 +14,9 @@ namespace DB namespace Cpu { -#if defined(__x86_64__) || defined(__i386__) -inline UInt64 _xgetbv(UInt32 xcr) noexcept +#if (defined(__x86_64__) || defined(__i386__)) +/// Our version is independent of -mxsave option, because we do dynamic dispatch. +inline UInt64 our_xgetbv(UInt32 xcr) noexcept { UInt32 eax; UInt32 edx; @@ -185,7 +186,7 @@ bool haveAVX() noexcept // http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf // https://bugs.chromium.org/p/chromium/issues/detail?id=375968 return haveOSXSAVE() // implies haveXSAVE() - && (_xgetbv(0) & 6u) == 6u // XMM state and YMM state are enabled by OS + && (our_xgetbv(0) & 6u) == 6u // XMM state and YMM state are enabled by OS && ((CpuInfo(0x1).ecx >> 28) & 1u); // AVX bit #else return false; @@ -217,8 +218,8 @@ bool haveAVX512F() noexcept #if defined(__x86_64__) || defined(__i386__) // https://software.intel.com/en-us/articles/how-to-detect-knl-instruction-support return haveOSXSAVE() // implies haveXSAVE() - && (_xgetbv(0) & 6u) == 6u // XMM state and YMM state are enabled by OS - && ((_xgetbv(0) >> 5) & 7u) == 7u // ZMM state is enabled by OS + && (our_xgetbv(0) & 6u) == 6u // XMM state and YMM state are enabled by OS + && ((our_xgetbv(0) >> 5) & 7u) == 7u // ZMM state is enabled by OS && CpuInfo(0x0).eax >= 0x7 // leaf 7 is present && ((CpuInfo(0x7).ebx >> 16) & 1u); // AVX512F bit #else diff --git a/dbms/src/Common/CurrentThread.cpp b/dbms/src/Common/CurrentThread.cpp index 6c2c77dccd7..5186cec0c41 100644 --- a/dbms/src/Common/CurrentThread.cpp +++ b/dbms/src/Common/CurrentThread.cpp @@ -23,7 +23,7 @@ void CurrentThread::updatePerformanceCounters() { if (unlikely(!current_thread)) return; - get().updatePerformanceCounters(); + current_thread->updatePerformanceCounters(); } ThreadStatus & CurrentThread::get() @@ -36,35 +36,35 @@ ThreadStatus & CurrentThread::get() ProfileEvents::Counters & CurrentThread::getProfileEvents() { - return current_thread ? get().performance_counters : ProfileEvents::global_counters; + return current_thread ? current_thread->performance_counters : ProfileEvents::global_counters; } MemoryTracker * CurrentThread::getMemoryTracker() { if (unlikely(!current_thread)) return nullptr; - return &get().memory_tracker; + return ¤t_thread->memory_tracker; } void CurrentThread::updateProgressIn(const Progress & value) { if (unlikely(!current_thread)) return; - get().progress_in.incrementPiecewiseAtomically(value); + current_thread->progress_in.incrementPiecewiseAtomically(value); } void CurrentThread::updateProgressOut(const Progress & value) { if (unlikely(!current_thread)) return; - get().progress_out.incrementPiecewiseAtomically(value); + current_thread->progress_out.incrementPiecewiseAtomically(value); } void CurrentThread::attachInternalTextLogsQueue(const std::shared_ptr & logs_queue) { if (unlikely(!current_thread)) return; - get().attachInternalTextLogsQueue(logs_queue); + current_thread->attachInternalTextLogsQueue(logs_queue); } std::shared_ptr CurrentThread::getInternalTextLogsQueue() @@ -73,10 +73,10 @@ std::shared_ptr CurrentThread::getInternalTextLogsQueue() if (unlikely(!current_thread)) return nullptr; - if (get().getCurrentState() == ThreadStatus::ThreadState::Died) + if (current_thread->getCurrentState() == ThreadStatus::ThreadState::Died) return nullptr; - return get().getInternalTextLogsQueue(); + return current_thread->getInternalTextLogsQueue(); } ThreadGroupStatusPtr CurrentThread::getGroup() @@ -84,7 +84,7 @@ ThreadGroupStatusPtr CurrentThread::getGroup() if (unlikely(!current_thread)) return nullptr; - return get().getThreadGroup(); + return current_thread->getThreadGroup(); } } diff --git a/dbms/src/Common/CurrentThread.h b/dbms/src/Common/CurrentThread.h index 49b46721008..3c248ad903f 100644 --- a/dbms/src/Common/CurrentThread.h +++ b/dbms/src/Common/CurrentThread.h @@ -3,6 +3,7 @@ #include #include +#include #include @@ -69,7 +70,7 @@ public: static void finalizePerformanceCounters(); /// Returns a non-empty string if the thread is attached to a query - static const std::string & getQueryId(); + static StringRef getQueryId(); /// Non-master threads call this method in destructor automatically static void detachQuery(); diff --git a/dbms/src/Common/DNSResolver.cpp b/dbms/src/Common/DNSResolver.cpp index bba3305684c..5314068b291 100644 --- a/dbms/src/Common/DNSResolver.cpp +++ b/dbms/src/Common/DNSResolver.cpp @@ -1,14 +1,23 @@ #include "DNSResolver.h" -#include +#include #include +#include +#include #include #include #include #include +#include +#include #include #include #include +namespace ProfileEvents +{ + extern Event NetworkErrors; +} + namespace DB { @@ -67,7 +76,6 @@ static void splitHostAndPort(const std::string & host_and_port, std::string & ou } } - static Poco::Net::IPAddress resolveIPAddressImpl(const std::string & host) { /// NOTE: Poco::Net::DNS::resolveOne(host) doesn't work for IP addresses like 127.0.0.2 @@ -75,15 +83,22 @@ static Poco::Net::IPAddress resolveIPAddressImpl(const std::string & host) return Poco::Net::SocketAddress(host, 0U).host(); } - struct DNSResolver::Impl { SimpleCache cache_host; + std::mutex drop_mutex; + std::mutex update_mutex; + /// Cached server host name - std::mutex mutex; std::optional host_name; + /// Store hosts, which was asked to resolve from last update of DNS cache. + NameSet new_hosts; + + /// Store all hosts, which was whenever asked to resolve + NameSet known_hosts; + /// If disabled, will not make cache lookups, will resolve addresses manually on each call std::atomic disable_cache{false}; }; @@ -93,28 +108,43 @@ DNSResolver::DNSResolver() : impl(std::make_unique()) {} Poco::Net::IPAddress DNSResolver::resolveHost(const std::string & host) { - return !impl->disable_cache ? impl->cache_host(host) : resolveIPAddressImpl(host); + if (impl->disable_cache) + return resolveIPAddressImpl(host); + + addToNewHosts(host); + return impl->cache_host(host); } Poco::Net::SocketAddress DNSResolver::resolveAddress(const std::string & host_and_port) { + if (impl->disable_cache) + return Poco::Net::SocketAddress(host_and_port); + String host; UInt16 port; splitHostAndPort(host_and_port, host, port); - return !impl->disable_cache ? Poco::Net::SocketAddress(impl->cache_host(host), port) : Poco::Net::SocketAddress(host_and_port); + addToNewHosts(host); + return Poco::Net::SocketAddress(impl->cache_host(host), port); } Poco::Net::SocketAddress DNSResolver::resolveAddress(const std::string & host, UInt16 port) { - return !impl->disable_cache ? Poco::Net::SocketAddress(impl->cache_host(host), port) : Poco::Net::SocketAddress(host, port); + if (impl->disable_cache) + return Poco::Net::SocketAddress(host, port); + + addToNewHosts(host); + return Poco::Net::SocketAddress(impl->cache_host(host), port); } void DNSResolver::dropCache() { impl->cache_host.drop(); - std::unique_lock lock(impl->mutex); + std::scoped_lock lock(impl->update_mutex, impl->drop_mutex); + + impl->known_hosts.clear(); + impl->new_hosts.clear(); impl->host_name.reset(); } @@ -128,7 +158,7 @@ String DNSResolver::getHostName() if (impl->disable_cache) return Poco::Net::DNS::hostName(); - std::unique_lock lock(impl->mutex); + std::lock_guard lock(impl->drop_mutex); if (!impl->host_name.has_value()) impl->host_name.emplace(Poco::Net::DNS::hostName()); @@ -136,6 +166,61 @@ String DNSResolver::getHostName() return *impl->host_name; } +bool DNSResolver::updateCache() +{ + { + std::lock_guard lock(impl->drop_mutex); + for (auto & host : impl->new_hosts) + impl->known_hosts.insert(std::move(host)); + impl->new_hosts.clear(); + + impl->host_name.emplace(Poco::Net::DNS::hostName()); + } + + std::lock_guard lock(impl->update_mutex); + + bool updated = false; + String lost_hosts; + for (const auto & host : impl->known_hosts) + { + try + { + updated |= updateHost(host); + } + catch (const Poco::Net::NetException &) + { + ProfileEvents::increment(ProfileEvents::NetworkErrors); + + if (!lost_hosts.empty()) + lost_hosts += ", "; + lost_hosts += host; + } + catch (...) + { + tryLogCurrentException(__PRETTY_FUNCTION__); + } + } + + if (!lost_hosts.empty()) + LOG_INFO(&Logger::get("DNSResolver"), "Cached hosts not found: " << lost_hosts); + + return updated; +} + +bool DNSResolver::updateHost(const String & host) +{ + /// Usage of updateHost implies that host is already in cache and there is no extra computations + auto old_value = impl->cache_host(host); + impl->cache_host.update(host); + return old_value != impl->cache_host(host); +} + +void DNSResolver::addToNewHosts(const String & host) +{ + std::lock_guard lock(impl->drop_mutex); + impl->new_hosts.insert(host); +} + DNSResolver::~DNSResolver() = default; diff --git a/dbms/src/Common/DNSResolver.h b/dbms/src/Common/DNSResolver.h index 097e646fa65..df646be9981 100644 --- a/dbms/src/Common/DNSResolver.h +++ b/dbms/src/Common/DNSResolver.h @@ -4,13 +4,15 @@ #include #include #include +#include namespace DB { -/// A singleton implementing DNS names resolving with optional permanent DNS cache -/// The cache could be updated only manually via drop() method +/// A singleton implementing DNS names resolving with optional DNS cache +/// The cache is being updated asynchronous in separate thread (see DNSCacheUpdater) +/// or it could be updated manually via drop() method. class DNSResolver : public ext::singleton { public: @@ -34,9 +36,13 @@ public: /// Drops all caches void dropCache(); + /// Updates all known hosts in cache. + /// Returns true if IP of any host has been changed. + bool updateCache(); + ~DNSResolver(); -protected: +private: DNSResolver(); @@ -44,6 +50,11 @@ protected: struct Impl; std::unique_ptr impl; + + /// Returns true if IP of host has been changed. + bool updateHost(const String & host); + + void addToNewHosts(const String & host); }; } diff --git a/dbms/src/Common/ErrorCodes.cpp b/dbms/src/Common/ErrorCodes.cpp index 5881f6bc501..a3b788c230f 100644 --- a/dbms/src/Common/ErrorCodes.cpp +++ b/dbms/src/Common/ErrorCodes.cpp @@ -430,7 +430,10 @@ namespace ErrorCodes extern const int MYSQL_CLIENT_INSUFFICIENT_CAPABILITIES = 453; extern const int OPENSSL_ERROR = 454; extern const int SUSPICIOUS_TYPE_FOR_LOW_CARDINALITY = 455; + extern const int UNKNOWN_QUERY_PARAMETER = 456; + extern const int BAD_QUERY_PARAMETER = 457; extern const int CANNOT_UNLINK = 458; + extern const int CANNOT_SET_THREAD_PRIORITY = 459; extern const int KEEPER_EXCEPTION = 999; extern const int POCO_EXCEPTION = 1000; diff --git a/dbms/src/Common/EventCounter.h b/dbms/src/Common/EventCounter.h new file mode 100644 index 00000000000..edd552ace83 --- /dev/null +++ b/dbms/src/Common/EventCounter.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include + + +/** Allow to subscribe for multiple events and wait for them one by one in arbitrary order. + */ +class EventCounter +{ +private: + size_t events_happened = 0; + size_t events_waited = 0; + + mutable std::mutex mutex; + std::condition_variable condvar; + +public: + void notify() + { + { + std::lock_guard lock(mutex); + ++events_happened; + } + condvar.notify_all(); + } + + void wait() + { + std::unique_lock lock(mutex); + condvar.wait(lock, [&]{ return events_happened > events_waited; }); + ++events_waited; + } + + template + bool waitFor(Duration && duration) + { + std::unique_lock lock(mutex); + if (condvar.wait(lock, std::forward(duration), [&]{ return events_happened > events_waited; })) + { + ++events_waited; + return true; + } + return false; + } +}; diff --git a/dbms/src/Common/Exception.h b/dbms/src/Common/Exception.h index 6b0656f4828..ee897962228 100644 --- a/dbms/src/Common/Exception.h +++ b/dbms/src/Common/Exception.h @@ -6,7 +6,7 @@ #include -#include +#include namespace Poco { class Logger; } diff --git a/dbms/src/Common/FileChecker.cpp b/dbms/src/Common/FileChecker.cpp index d196c703e36..5256b683653 100644 --- a/dbms/src/Common/FileChecker.cpp +++ b/dbms/src/Common/FileChecker.cpp @@ -42,35 +42,40 @@ void FileChecker::update(const Files::const_iterator & begin, const Files::const save(); } -bool FileChecker::check() const +CheckResults FileChecker::check() const { /** Read the files again every time you call `check` - so as not to violate the constancy. * `check` method is rarely called. */ + + CheckResults results; Map local_map; load(local_map, files_info_path); if (local_map.empty()) - return true; + return {}; for (const auto & name_size : local_map) { - Poco::File file(Poco::Path(files_info_path).parent().toString() + "/" + name_size.first); + Poco::Path path = Poco::Path(files_info_path).parent().toString() + "/" + name_size.first; + Poco::File file(path); if (!file.exists()) { - LOG_ERROR(log, "File " << file.path() << " doesn't exist"); - return false; + results.emplace_back(path.getFileName(), false, "File " + file.path() + " doesn't exist"); + break; } + size_t real_size = file.getSize(); if (real_size != name_size.second) { - LOG_ERROR(log, "Size of " << file.path() << " is wrong. Size is " << real_size << " but should be " << name_size.second); - return false; + results.emplace_back(path.getFileName(), false, "Size of " + file.path() + " is wrong. Size is " + toString(real_size) + " but should be " + toString(name_size.second)); + break; } + results.emplace_back(path.getFileName(), true, ""); } - return true; + return results; } void FileChecker::initialize() diff --git a/dbms/src/Common/FileChecker.h b/dbms/src/Common/FileChecker.h index 26167826888..bd69867b11c 100644 --- a/dbms/src/Common/FileChecker.h +++ b/dbms/src/Common/FileChecker.h @@ -3,6 +3,7 @@ #include #include #include +#include namespace DB @@ -24,7 +25,7 @@ public: void update(const Files::const_iterator & begin, const Files::const_iterator & end); /// Check the files whose parameters are specified in sizes.json - bool check() const; + CheckResults check() const; private: void initialize(); diff --git a/dbms/src/Common/MiAllocator.cpp b/dbms/src/Common/MiAllocator.cpp new file mode 100644 index 00000000000..456609374ee --- /dev/null +++ b/dbms/src/Common/MiAllocator.cpp @@ -0,0 +1,43 @@ +#include + +#if USE_MIMALLOC + +#include "MiAllocator.h" +#include + +namespace DB +{ + +void * MiAllocator::alloc(size_t size, size_t alignment) +{ + if (alignment == 0) + return mi_malloc(size); + else + return mi_malloc_aligned(size, alignment); +} + +void MiAllocator::free(void * buf, size_t) +{ + mi_free(buf); +} + +void * MiAllocator::realloc(void * old_ptr, size_t, size_t new_size, size_t alignment) +{ + if (old_ptr == nullptr) + return alloc(new_size, alignment); + + if (new_size == 0) + { + mi_free(old_ptr); + return nullptr; + } + + if (alignment == 0) + return mi_realloc(old_ptr, alignment); + + return mi_realloc_aligned(old_ptr, new_size, alignment); +} + +} + +#endif diff --git a/dbms/src/Common/MiAllocator.h b/dbms/src/Common/MiAllocator.h index 075328e5d94..48cfc6f9ab4 100644 --- a/dbms/src/Common/MiAllocator.h +++ b/dbms/src/Common/MiAllocator.h @@ -6,7 +6,6 @@ #error "do not include this file until USE_MIMALLOC is set to 1" #endif -#include #include namespace DB @@ -19,37 +18,11 @@ namespace DB */ struct MiAllocator { + static void * alloc(size_t size, size_t alignment = 0); - static void * alloc(size_t size, size_t alignment = 0) - { - if (alignment == 0) - return mi_malloc(size); - else - return mi_malloc_aligned(size, alignment); - } - - static void free(void * buf, size_t) - { - mi_free(buf); - } - - static void * realloc(void * old_ptr, size_t, size_t new_size, size_t alignment = 0) - { - if (old_ptr == nullptr) - return alloc(new_size, alignment); - - if (new_size == 0) - { - mi_free(old_ptr); - return nullptr; - } - - if (alignment == 0) - return mi_realloc(old_ptr, alignment); - - return mi_realloc_aligned(old_ptr, new_size, alignment); - } + static void free(void * buf, size_t); + static void * realloc(void * old_ptr, size_t, size_t new_size, size_t alignment = 0); }; } diff --git a/dbms/src/Common/PODArray.h b/dbms/src/Common/PODArray.h index 0e7d547a7d0..01085a2c5a7 100644 --- a/dbms/src/Common/PODArray.h +++ b/dbms/src/Common/PODArray.h @@ -45,7 +45,7 @@ inline constexpr size_t integerRoundUp(size_t value, size_t dividend) * Only part of the std::vector interface is supported. * * The default constructor creates an empty object that does not allocate memory. - * Then the memory is allocated at least INITIAL_SIZE bytes. + * Then the memory is allocated at least initial_bytes bytes. * * If you insert elements with push_back, without making a `reserve`, then PODArray is about 2.5 times faster than std::vector. * @@ -74,7 +74,7 @@ extern const char EmptyPODArray[EmptyPODArraySize]; /** Base class that depend only on size of element, not on element itself. * You can static_cast to this class if you want to insert some data regardless to the actual type T. */ -template +template class PODArrayBase : private boost::noncopyable, private TAllocator /// empty base optimization { protected: @@ -161,7 +161,8 @@ protected: { // The allocated memory should be multiplication of ELEMENT_SIZE to hold the element, otherwise, // memory issue such as corruption could appear in edge case. - realloc(std::max(((INITIAL_SIZE - 1) / ELEMENT_SIZE + 1) * ELEMENT_SIZE, minimum_memory_for_elements(1)), + realloc(std::max(integerRoundUp(initial_bytes, ELEMENT_SIZE), + minimum_memory_for_elements(1)), std::forward(allocator_params)...); } else @@ -257,11 +258,11 @@ public: } }; -template , size_t pad_right_ = 0, size_t pad_left_ = 0> -class PODArray : public PODArrayBase +template , size_t pad_right_ = 0, size_t pad_left_ = 0> +class PODArray : public PODArrayBase { protected: - using Base = PODArrayBase; + using Base = PODArrayBase; T * t_start() { return reinterpret_cast(this->c_start); } T * t_end() { return reinterpret_cast(this->c_end); } @@ -618,17 +619,23 @@ public: } }; -template -void swap(PODArray & lhs, PODArray & rhs) +template +void swap(PODArray & lhs, PODArray & rhs) { lhs.swap(rhs); } /** For columns. Padding is enough to read and write xmm-register at the address of the last element. */ -template > -using PaddedPODArray = PODArray; +template > +using PaddedPODArray = PODArray; -template -using PODArrayWithStackMemory = PODArray, integerRoundUp(stack_size_in_bytes, sizeof(T))>>; +/** A helper for declaring PODArray that uses inline memory. + * The initial size is set to use all the inline bytes, since using less would + * only add some extra allocation calls. + */ +template +using PODArrayWithStackMemory = PODArray, rounded_bytes>>; } diff --git a/dbms/src/Common/SpaceSaving.h b/dbms/src/Common/SpaceSaving.h index a681279a515..56dbf382293 100644 --- a/dbms/src/Common/SpaceSaving.h +++ b/dbms/src/Common/SpaceSaving.h @@ -167,6 +167,16 @@ public: } auto min = counter_list.back(); + // The key doesn't exist and cannot fit in the current top K, but + // the new key has a bigger weight and is virtually more present + // compared to the element who is less present on the set. This part + // of the code is useful for the function topKWeighted + if (increment > min->count) + { + destroyLastElement(); + push(new Counter(arena.emplace(key), increment, error, hash)); + return; + } const size_t alpha_mask = alpha_map.size() - 1; auto & alpha = alpha_map[hash & alpha_mask]; if (alpha + increment < min->count) @@ -333,6 +343,17 @@ private: alpha_map.clear(); } + void destroyLastElement() + { + auto last_element = counter_list.back(); + auto cell = counter_map.find(last_element->key, last_element->hash); + cell->setZero(); + counter_map.reinsert(cell, last_element->hash); + counter_list.pop_back(); + arena.free(last_element->key); + delete last_element; + } + HashMap counter_map; std::vector counter_list; std::vector alpha_map; diff --git a/dbms/src/Common/StackTrace.cpp b/dbms/src/Common/StackTrace.cpp deleted file mode 100644 index e8ba21a187a..00000000000 --- a/dbms/src/Common/StackTrace.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#if !defined(__APPLE__) && !defined(__FreeBSD__) -#include -#endif -#include -#include - -#include - -#include -#include - -#include - - -/// Arcadia compatibility DEVTOOLS-3976 -#if defined(BACKTRACE_INCLUDE) -#include BACKTRACE_INCLUDE -#endif -#if !defined(BACKTRACE_FUNC) - #define BACKTRACE_FUNC backtrace -#endif - -StackTrace::StackTrace() -{ - frames_size = BACKTRACE_FUNC(frames.data(), STACK_TRACE_MAX_DEPTH); - - for (size_t i = frames_size; i < STACK_TRACE_MAX_DEPTH; ++i) - frames[i] = nullptr; -} - - -std::string StackTrace::toStringImpl(const Frames & frames, size_t frames_size) -{ - char ** symbols = backtrace_symbols(frames.data(), frames_size); - if (!symbols) - return "Cannot get symbols for stack trace.\n"; - - std::stringstream res; - try - { - for (size_t i = 0, size = frames_size; i < size; ++i) - { - /// We do "demangling" of names. The name is in parenthesis, before the '+' character. - - char * name_start = nullptr; - char * name_end = nullptr; - std::string demangled_name; - int status = 0; - - if (nullptr != (name_start = strchr(symbols[i], '(')) - && nullptr != (name_end = strchr(name_start, '+'))) - { - ++name_start; - *name_end = '\0'; - demangled_name = demangle(name_start, status); - *name_end = '+'; - } - - res << i << ". "; - - if (0 == status && name_start && name_end) - { - res.write(symbols[i], name_start - symbols[i]); - res << demangled_name << name_end; - } - else - res << symbols[i]; - - res << std::endl; - } - } - catch (...) - { - free(symbols); - throw; - } - - free(symbols); - return res.str(); -} - - -std::string StackTrace::toString() const -{ - /// Calculation of stack trace text is extremely slow. - /// We use simple cache because otherwise the server could be overloaded by trash queries. - - static SimpleCache func_cached; - return func_cached(frames, frames_size); -} diff --git a/dbms/src/Common/StackTrace.h b/dbms/src/Common/StackTrace.h deleted file mode 100644 index 055bca7e21e..00000000000 --- a/dbms/src/Common/StackTrace.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include - -#define STACK_TRACE_MAX_DEPTH 32 - - -/// Lets you get a stacktrace -class StackTrace -{ -public: - /// The stacktrace is captured when the object is created - StackTrace(); - - /// Print to string - std::string toString() const; - -private: - using Frame = void*; - using Frames = std::array; - Frames frames; - size_t frames_size; - - static std::string toStringImpl(const Frames & frames, size_t frames_size); -}; diff --git a/dbms/src/Common/Stopwatch.h b/dbms/src/Common/Stopwatch.h index d6508b23b44..7bfaccc72b2 100644 --- a/dbms/src/Common/Stopwatch.h +++ b/dbms/src/Common/Stopwatch.h @@ -189,3 +189,16 @@ private: Timestamp stop_ts; bool is_running = false; }; + + +template +class StopwatchGuard : public TStopwatch +{ +public: + explicit StopwatchGuard(UInt64 & elapsed_ns_) : elapsed_ns(elapsed_ns_) {} + + ~StopwatchGuard() { elapsed_ns += TStopwatch::elapsedNanoseconds(); } + +private: + UInt64 & elapsed_ns; +}; diff --git a/dbms/src/Common/ThreadPool.cpp b/dbms/src/Common/ThreadPool.cpp index 6ed350240c6..91ec29dc188 100644 --- a/dbms/src/Common/ThreadPool.cpp +++ b/dbms/src/Common/ThreadPool.cpp @@ -30,10 +30,18 @@ template template ReturnType ThreadPoolImpl::scheduleImpl(Job job, int priority, std::optional wait_microseconds) { - auto on_error = [] + auto on_error = [&] { if constexpr (std::is_same_v) + { + if (first_exception) + { + std::exception_ptr exception; + std::swap(exception, first_exception); + std::rethrow_exception(exception); + } throw DB::Exception("Cannot schedule a task", DB::ErrorCodes::CANNOT_SCHEDULE_TASK); + } else return false; }; diff --git a/dbms/src/Common/ThreadStatus.h b/dbms/src/Common/ThreadStatus.h index f92d604b372..0d36024b15d 100644 --- a/dbms/src/Common/ThreadStatus.h +++ b/dbms/src/Common/ThreadStatus.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -85,6 +86,8 @@ public: UInt32 thread_number = 0; /// Linux's PID (or TGID) (the same id is shown by ps util) Int32 os_thread_id = -1; + /// Also called "nice" value. If it was changed to non-zero (when attaching query) - will be reset to zero when query is detached. + Int32 os_thread_priority = 0; /// TODO: merge them into common entity ProfileEvents::Counters performance_counters{VariableContext::Thread}; @@ -114,7 +117,7 @@ public: return thread_state.load(std::memory_order_relaxed); } - const std::string & getQueryId() const; + StringRef getQueryId() const; /// Starts new query and create new thread group for it, current thread becomes master thread of the query void initializeQuery(); diff --git a/dbms/src/Common/ZooKeeper/tests/gtest_zkutil_test_multi_exception.cpp b/dbms/src/Common/ZooKeeper/tests/gtest_zkutil_test_multi_exception.cpp index 489ac04c5e4..2f332c7039d 100644 --- a/dbms/src/Common/ZooKeeper/tests/gtest_zkutil_test_multi_exception.cpp +++ b/dbms/src/Common/ZooKeeper/tests/gtest_zkutil_test_multi_exception.cpp @@ -5,11 +5,6 @@ #include #include -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ - #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" - #pragma clang diagnostic ignored "-Wundef" -#endif #include #include diff --git a/dbms/src/Common/formatIPv6.cpp b/dbms/src/Common/formatIPv6.cpp index f8100557ba2..9ec6c427ab4 100644 --- a/dbms/src/Common/formatIPv6.cpp +++ b/dbms/src/Common/formatIPv6.cpp @@ -153,7 +153,7 @@ void formatIPv6(const unsigned char * src, char *& dst, UInt8 zeroed_tail_bytes_ } /// Was it a trailing run of 0x00's? - if (best.base != -1 && size_t(best.base + best.len) == words.size()) + if (best.base != -1 && size_t(best.base) + size_t(best.len) == words.size()) *dst++ = ':'; *dst++ = '\0'; diff --git a/dbms/src/Common/isLocalAddress.h b/dbms/src/Common/isLocalAddress.h index 81039dff68e..63de5e000a9 100644 --- a/dbms/src/Common/isLocalAddress.h +++ b/dbms/src/Common/isLocalAddress.h @@ -23,9 +23,7 @@ namespace DB * - the routing rules that affect which network interface we go to the specified address are not checked. */ bool isLocalAddress(const Poco::Net::SocketAddress & address, UInt16 clickhouse_port); - bool isLocalAddress(const Poco::Net::SocketAddress & address); - bool isLocalAddress(const Poco::Net::IPAddress & address); /// Returns number of different bytes in hostnames, used for load balancing diff --git a/dbms/src/Common/tests/CMakeLists.txt b/dbms/src/Common/tests/CMakeLists.txt index 1c6c7e9f504..fb28dd14a43 100644 --- a/dbms/src/Common/tests/CMakeLists.txt +++ b/dbms/src/Common/tests/CMakeLists.txt @@ -23,10 +23,10 @@ add_executable (small_table small_table.cpp) target_link_libraries (small_table PRIVATE clickhouse_common_io) add_executable (parallel_aggregation parallel_aggregation.cpp) -target_link_libraries (parallel_aggregation PRIVATE clickhouse_compression clickhouse_common_io) +target_link_libraries (parallel_aggregation PRIVATE dbms) add_executable (parallel_aggregation2 parallel_aggregation2.cpp) -target_link_libraries (parallel_aggregation2 PRIVATE clickhouse_compression clickhouse_common_io) +target_link_libraries (parallel_aggregation2 PRIVATE dbms) add_executable (int_hashes_perf int_hashes_perf.cpp AvalancheTest.cpp Random.cpp) target_link_libraries (int_hashes_perf PRIVATE clickhouse_common_io) @@ -41,11 +41,8 @@ target_link_libraries (compact_array PRIVATE clickhouse_common_io ${Boost_FILESY add_executable (radix_sort radix_sort.cpp) target_link_libraries (radix_sort PRIVATE clickhouse_common_io) -add_executable (shell_command_test shell_command_test.cpp) -target_link_libraries (shell_command_test PRIVATE clickhouse_common_io) - add_executable (arena_with_free_lists arena_with_free_lists.cpp) -target_link_libraries (arena_with_free_lists PRIVATE clickhouse_compression clickhouse_common_io) +target_link_libraries (arena_with_free_lists PRIVATE dbms) add_executable (pod_array pod_array.cpp) target_link_libraries (pod_array PRIVATE clickhouse_common_io) @@ -53,15 +50,6 @@ target_link_libraries (pod_array PRIVATE clickhouse_common_io) add_executable (thread_creation_latency thread_creation_latency.cpp) target_link_libraries (thread_creation_latency PRIVATE clickhouse_common_io) -add_executable (thread_pool thread_pool.cpp) -target_link_libraries (thread_pool PRIVATE clickhouse_common_io) - -add_executable (thread_pool_2 thread_pool_2.cpp) -target_link_libraries (thread_pool_2 PRIVATE clickhouse_common_io) - -add_executable (thread_pool_3 thread_pool_3.cpp) -target_link_libraries (thread_pool_3 PRIVATE clickhouse_common_io) - add_executable (multi_version multi_version.cpp) target_link_libraries (multi_version PRIVATE clickhouse_common_io) add_check(multi_version) @@ -74,7 +62,7 @@ target_link_libraries (space_saving PRIVATE clickhouse_common_io) add_executable (integer_hash_tables_and_hashes integer_hash_tables_and_hashes.cpp) target_include_directories (integer_hash_tables_and_hashes SYSTEM BEFORE PRIVATE ${SPARCEHASH_INCLUDE_DIR}) -target_link_libraries (integer_hash_tables_and_hashes PRIVATE clickhouse_compression clickhouse_common_io) +target_link_libraries (integer_hash_tables_and_hashes PRIVATE dbms) add_executable (allocator allocator.cpp) target_link_libraries (allocator PRIVATE clickhouse_common_io) diff --git a/dbms/src/Common/tests/gtest_rw_lock.cpp b/dbms/src/Common/tests/gtest_rw_lock.cpp index 6e9b91dc048..68927c8bc4a 100644 --- a/dbms/src/Common/tests/gtest_rw_lock.cpp +++ b/dbms/src/Common/tests/gtest_rw_lock.cpp @@ -1,8 +1,3 @@ -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ - #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" - #pragma clang diagnostic ignored "-Wundef" -#endif #include #include diff --git a/dbms/src/Common/tests/gtest_shell_command.cpp b/dbms/src/Common/tests/gtest_shell_command.cpp new file mode 100644 index 00000000000..79b8309d0fa --- /dev/null +++ b/dbms/src/Common/tests/gtest_shell_command.cpp @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +using namespace DB; + + +TEST(ShellCommand, Execute) +{ + auto command = ShellCommand::execute("echo 'Hello, world!'"); + + std::string res; + readStringUntilEOF(res, command->out); + command->wait(); + + EXPECT_EQ(res, "Hello, world!\n"); +} + +TEST(ShellCommand, ExecuteDirect) +{ + auto command = ShellCommand::executeDirect("/bin/echo", {"Hello, world!"}); + + std::string res; + readStringUntilEOF(res, command->out); + command->wait(); + + EXPECT_EQ(res, "Hello, world!\n"); +} + +TEST(ShellCommand, ExecuteWithInput) +{ + auto command = ShellCommand::execute("cat"); + + String in_str = "Hello, world!\n"; + ReadBufferFromString in(in_str); + copyData(in, command->in); + command->in.close(); + + std::string res; + readStringUntilEOF(res, command->out); + command->wait(); + + EXPECT_EQ(res, "Hello, world!\n"); +} + +TEST(ShellCommand, AutoWait) +{ + // hunting: + for (int i = 0; i < 1000; ++i) + { + auto command = ShellCommand::execute("echo " + std::to_string(i)); + //command->wait(); // now automatic + } + + // std::cerr << "inspect me: ps auxwwf" << "\n"; + // std::this_thread::sleep_for(std::chrono::seconds(100)); +} diff --git a/dbms/src/Common/tests/thread_pool.cpp b/dbms/src/Common/tests/gtest_thread_pool_concurrent_wait.cpp similarity index 92% rename from dbms/src/Common/tests/thread_pool.cpp rename to dbms/src/Common/tests/gtest_thread_pool_concurrent_wait.cpp index 23dba2aadec..213e70ce3dd 100644 --- a/dbms/src/Common/tests/thread_pool.cpp +++ b/dbms/src/Common/tests/gtest_thread_pool_concurrent_wait.cpp @@ -1,11 +1,13 @@ #include +#include + /** Reproduces bug in ThreadPool. * It get stuck if we call 'wait' many times from many other threads simultaneously. */ -int main(int, char **) +TEST(ThreadPool, ConcurrentWait) { auto worker = [] { @@ -29,6 +31,4 @@ int main(int, char **) waiting_pool.schedule([&pool]{ pool.wait(); }); waiting_pool.wait(); - - return 0; } diff --git a/dbms/src/Common/tests/thread_pool_3.cpp b/dbms/src/Common/tests/gtest_thread_pool_limit.cpp similarity index 52% rename from dbms/src/Common/tests/thread_pool_3.cpp rename to dbms/src/Common/tests/gtest_thread_pool_limit.cpp index 924895de308..c18ff2e38ee 100644 --- a/dbms/src/Common/tests/thread_pool_3.cpp +++ b/dbms/src/Common/tests/gtest_thread_pool_limit.cpp @@ -1,27 +1,27 @@ -#include +#include #include #include +#include + /// Test for thread self-removal when number of free threads in pool is too large. /// Just checks that nothing weird happens. template -void test() +int test() { Pool pool(10, 2, 10); - std::mutex mutex; + std::atomic counter{0}; for (size_t i = 0; i < 10; ++i) - pool.schedule([&]{ std::lock_guard lock(mutex); std::cerr << '.'; }); + pool.schedule([&]{ ++counter; }); pool.wait(); + + return counter; } -int main(int, char **) +TEST(ThreadPool, ThreadRemoval) { - test(); - std::cerr << '\n'; - test(); - std::cerr << '\n'; - - return 0; + EXPECT_EQ(test(), 10); + EXPECT_EQ(test(), 10); } diff --git a/dbms/src/Common/tests/thread_pool_2.cpp b/dbms/src/Common/tests/gtest_thread_pool_loop.cpp similarity index 73% rename from dbms/src/Common/tests/thread_pool_2.cpp rename to dbms/src/Common/tests/gtest_thread_pool_loop.cpp index 029c3695e36..63d4114b867 100644 --- a/dbms/src/Common/tests/thread_pool_2.cpp +++ b/dbms/src/Common/tests/gtest_thread_pool_loop.cpp @@ -2,10 +2,12 @@ #include #include +#include -int main(int, char **) + +TEST(ThreadPool, Loop) { - std::atomic res{0}; + std::atomic res{0}; for (size_t i = 0; i < 1000; ++i) { @@ -16,6 +18,5 @@ int main(int, char **) pool.wait(); } - std::cerr << res << "\n"; - return 0; + EXPECT_EQ(res, 16000); } diff --git a/dbms/src/Common/tests/gtest_thread_pool_schedule_exception.cpp b/dbms/src/Common/tests/gtest_thread_pool_schedule_exception.cpp new file mode 100644 index 00000000000..52091a1ea7f --- /dev/null +++ b/dbms/src/Common/tests/gtest_thread_pool_schedule_exception.cpp @@ -0,0 +1,33 @@ +#include +#include +#include + +#include + + +bool check() +{ + ThreadPool pool(10); + + pool.schedule([]{ throw std::runtime_error("Hello, world!"); }); + + try + { + for (size_t i = 0; i < 100; ++i) + pool.schedule([]{}); /// An exception will be rethrown from this method. + } + catch (const std::runtime_error &) + { + return true; + } + + pool.wait(); + + return false; +} + + +TEST(ThreadPool, ExceptionFromSchedule) +{ + EXPECT_TRUE(check()); +} diff --git a/dbms/src/Common/tests/gtest_unescapeForFileName.cpp b/dbms/src/Common/tests/gtest_unescapeForFileName.cpp index b7e045b4318..33194a6dade 100644 --- a/dbms/src/Common/tests/gtest_unescapeForFileName.cpp +++ b/dbms/src/Common/tests/gtest_unescapeForFileName.cpp @@ -1,10 +1,5 @@ #include -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ - #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" - #pragma clang diagnostic ignored "-Wundef" -#endif #include diff --git a/dbms/src/Common/tests/parallel_aggregation2.cpp b/dbms/src/Common/tests/parallel_aggregation2.cpp index 5bee292f58d..a2b26e82420 100644 --- a/dbms/src/Common/tests/parallel_aggregation2.cpp +++ b/dbms/src/Common/tests/parallel_aggregation2.cpp @@ -34,7 +34,7 @@ struct AggregateIndependent { results.reserve(num_threads); for (size_t i = 0; i < num_threads; ++i) - results.emplace_back(new Map); + results.emplace_back(std::make_unique()); for (size_t i = 0; i < num_threads; ++i) { @@ -77,7 +77,7 @@ struct AggregateIndependentWithSequentialKeysOptimization { results.reserve(num_threads); for (size_t i = 0; i < num_threads; ++i) - results.emplace_back(new Map); + results.emplace_back(std::make_unique()); for (size_t i = 0; i < num_threads; ++i) { diff --git a/dbms/src/Common/tests/shell_command_test.cpp b/dbms/src/Common/tests/shell_command_test.cpp deleted file mode 100644 index 7de6c18bfdf..00000000000 --- a/dbms/src/Common/tests/shell_command_test.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include - -using namespace DB; - - -int main(int, char **) -try -{ - { - auto command = ShellCommand::execute("echo 'Hello, world!'"); - - WriteBufferFromFileDescriptor out(STDOUT_FILENO); - copyData(command->out, out); - - command->wait(); - } - - { - auto command = ShellCommand::executeDirect("/bin/echo", {"Hello, world!"}); - - WriteBufferFromFileDescriptor out(STDOUT_FILENO); - copyData(command->out, out); - - command->wait(); - } - - { - auto command = ShellCommand::execute("cat"); - - String in_str = "Hello, world!\n"; - ReadBufferFromString in(in_str); - copyData(in, command->in); - command->in.close(); - - WriteBufferFromFileDescriptor out(STDOUT_FILENO); - copyData(command->out, out); - - command->wait(); - } - - // hunting: - for (int i = 0; i < 1000; ++i) - { - auto command = ShellCommand::execute("echo " + std::to_string(i)); - //command->wait(); // now automatic - } - - // std::cerr << "inspect me: ps auxwwf" << "\n"; - // std::this_thread::sleep_for(std::chrono::seconds(100)); -} -catch (...) -{ - std::cerr << getCurrentExceptionMessage(false) << "\n"; - return 1; -} diff --git a/dbms/src/Common/tests/simple_cache.cpp b/dbms/src/Common/tests/simple_cache.cpp index 93ddb30c6e9..34346e67fd4 100644 --- a/dbms/src/Common/tests/simple_cache.cpp +++ b/dbms/src/Common/tests/simple_cache.cpp @@ -1,5 +1,5 @@ #include -#include +#include int func(int x, int y) diff --git a/dbms/src/Compression/CMakeLists.txt b/dbms/src/Compression/CMakeLists.txt index 0032186205a..36cab0b3590 100644 --- a/dbms/src/Compression/CMakeLists.txt +++ b/dbms/src/Compression/CMakeLists.txt @@ -1,21 +1,3 @@ -include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake) -add_headers_and_sources(clickhouse_compression .) -add_library(clickhouse_compression ${clickhouse_compression_headers} ${clickhouse_compression_sources}) -target_link_libraries(clickhouse_compression PRIVATE clickhouse_parsers clickhouse_common_io ${LZ4_LIBRARY} ${CITYHASH_LIBRARIES}) -if(ZSTD_LIBRARY) - target_link_libraries(clickhouse_compression PRIVATE ${ZSTD_LIBRARY}) -endif() - -target_include_directories(clickhouse_compression PUBLIC ${DBMS_INCLUDE_DIR}) -target_include_directories(clickhouse_compression SYSTEM PUBLIC ${PCG_RANDOM_INCLUDE_DIR}) - -if (NOT USE_INTERNAL_LZ4_LIBRARY) - target_include_directories(clickhouse_compression SYSTEM BEFORE PRIVATE ${LZ4_INCLUDE_DIR}) -endif () -if (NOT USE_INTERNAL_ZSTD_LIBRARY AND ZSTD_INCLUDE_DIR) - target_include_directories(clickhouse_compression SYSTEM BEFORE PRIVATE ${ZSTD_INCLUDE_DIR}) -endif () - if(ENABLE_TESTS) add_subdirectory(tests) endif() diff --git a/dbms/src/Compression/CompressionCodecDelta.cpp b/dbms/src/Compression/CompressionCodecDelta.cpp index f5a5db04927..9f2397f8e59 100644 --- a/dbms/src/Compression/CompressionCodecDelta.cpp +++ b/dbms/src/Compression/CompressionCodecDelta.cpp @@ -67,7 +67,7 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest) while (source < source_end) { accumulator += unalignedLoad(source); - unalignedStore(dest, accumulator); + unalignedStore(dest, accumulator); source += sizeof(T); dest += sizeof(T); diff --git a/dbms/src/Compression/CompressionCodecDoubleDelta.cpp b/dbms/src/Compression/CompressionCodecDoubleDelta.cpp index b40b2abccfa..80d363e0ec5 100644 --- a/dbms/src/Compression/CompressionCodecDoubleDelta.cpp +++ b/dbms/src/Compression/CompressionCodecDoubleDelta.cpp @@ -83,6 +83,7 @@ WriteSpec getWriteSpec(const T & value) template UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) { + static_assert(std::is_unsigned_v && std::is_signed_v, "T must be unsigned, while DeltaType must be signed integer type."); using UnsignedDeltaType = typename std::make_unsigned::type; if (source_size % sizeof(T) != 0) @@ -90,7 +91,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) const char * source_end = source + source_size; const UInt32 items_count = source_size / sizeof(T); - unalignedStore(dest, items_count); + unalignedStore(dest, items_count); dest += sizeof(items_count); T prev_value{}; @@ -99,7 +100,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) if (source < source_end) { prev_value = unalignedLoad(source); - unalignedStore(dest, prev_value); + unalignedStore(dest, prev_value); source += sizeof(prev_value); dest += sizeof(prev_value); @@ -109,7 +110,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) { const T curr_value = unalignedLoad(source); prev_delta = static_cast(curr_value - prev_value); - unalignedStore(dest, prev_delta); + unalignedStore(dest, prev_delta); source += sizeof(curr_value); dest += sizeof(prev_delta); @@ -123,8 +124,8 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) { const T curr_value = unalignedLoad(source); - const auto delta = curr_value - prev_value; - const DeltaType double_delta = static_cast(delta - static_cast(prev_delta)); + const DeltaType delta = static_cast(curr_value - prev_value); + const DeltaType double_delta = delta - prev_delta; prev_delta = delta; prev_value = curr_value; @@ -153,6 +154,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) template void decompressDataForType(const char * source, UInt32 source_size, char * dest) { + static_assert(std::is_unsigned_v && std::is_signed_v, "T must be unsigned, while DeltaType must be signed integer type."); const char * source_end = source + source_size; const UInt32 items_count = unalignedLoad(source); @@ -164,7 +166,7 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest) if (source < source_end) { prev_value = unalignedLoad(source); - unalignedStore(dest, prev_value); + unalignedStore(dest, prev_value); source += sizeof(prev_value); dest += sizeof(prev_value); @@ -173,8 +175,8 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest) if (source < source_end) { prev_delta = unalignedLoad(source); - prev_value = static_cast(prev_value + prev_delta); - unalignedStore(dest, prev_value); + prev_value = prev_value + static_cast(prev_delta); + unalignedStore(dest, prev_value); source += sizeof(prev_delta); dest += sizeof(prev_value); @@ -208,11 +210,11 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest) } // else if first bit is zero, no need to read more data. - const T curr_value = static_cast(prev_value + prev_delta + double_delta); - unalignedStore(dest, curr_value); + const T curr_value = prev_value + static_cast(prev_delta + double_delta); + unalignedStore(dest, curr_value); dest += sizeof(curr_value); - prev_delta = curr_value - prev_value; + prev_delta = static_cast(curr_value - prev_value); prev_value = curr_value; } } diff --git a/dbms/src/Compression/CompressionCodecGorilla.cpp b/dbms/src/Compression/CompressionCodecGorilla.cpp index f9c6b52756c..79cc6d27e81 100644 --- a/dbms/src/Compression/CompressionCodecGorilla.cpp +++ b/dbms/src/Compression/CompressionCodecGorilla.cpp @@ -94,7 +94,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) const UInt32 items_count = source_size / sizeof(T); - unalignedStore(dest, items_count); + unalignedStore(dest, items_count); dest += sizeof(items_count); T prev_value{}; @@ -104,7 +104,7 @@ UInt32 compressDataForType(const char * source, UInt32 source_size, char * dest) if (source < source_end) { prev_value = unalignedLoad(source); - unalignedStore(dest, prev_value); + unalignedStore(dest, prev_value); source += sizeof(prev_value); dest += sizeof(prev_value); @@ -166,7 +166,7 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest) if (source < source_end) { prev_value = unalignedLoad(source); - unalignedStore(dest, prev_value); + unalignedStore(dest, prev_value); source += sizeof(prev_value); dest += sizeof(prev_value); @@ -210,7 +210,7 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest) } // else: 0b0 prefix - use prev_value - unalignedStore(dest, curr_value); + unalignedStore(dest, curr_value); dest += sizeof(curr_value); prev_xored_info = curr_xored_info; diff --git a/dbms/src/Compression/CompressionCodecT64.cpp b/dbms/src/Compression/CompressionCodecT64.cpp index cd369fc9c4e..b53670b9ceb 100644 --- a/dbms/src/Compression/CompressionCodecT64.cpp +++ b/dbms/src/Compression/CompressionCodecT64.cpp @@ -91,9 +91,10 @@ TypeIndex typeIdx(const DataTypePtr & data_type) return TypeIndex::Nothing; } -void transpose64x8(const UInt64 * src, UInt64 * dst, UInt32) +void transpose64x8(UInt64 * src_dst) { - auto * src8 = reinterpret_cast(src); + auto * src8 = reinterpret_cast(src_dst); + UInt64 dst[8] = {}; for (UInt32 i = 0; i < 64; ++i) { @@ -107,142 +108,171 @@ void transpose64x8(const UInt64 * src, UInt64 * dst, UInt32) dst[6] |= ((value >> 6) & 0x1) << i; dst[7] |= ((value >> 7) & 0x1) << i; } + + memcpy(src_dst, dst, 8 * sizeof(UInt64)); } -void revTranspose64x8(const UInt64 * src, UInt64 * dst, UInt32) +void reverseTranspose64x8(UInt64 * src_dst) { - auto * dst8 = reinterpret_cast(dst); + UInt8 dst8[64]; for (UInt32 i = 0; i < 64; ++i) { - dst8[i] = ((src[0] >> i) & 0x1) - | (((src[1] >> i) & 0x1) << 1) - | (((src[2] >> i) & 0x1) << 2) - | (((src[3] >> i) & 0x1) << 3) - | (((src[4] >> i) & 0x1) << 4) - | (((src[5] >> i) & 0x1) << 5) - | (((src[6] >> i) & 0x1) << 6) - | (((src[7] >> i) & 0x1) << 7); + dst8[i] = ((src_dst[0] >> i) & 0x1) + | (((src_dst[1] >> i) & 0x1) << 1) + | (((src_dst[2] >> i) & 0x1) << 2) + | (((src_dst[3] >> i) & 0x1) << 3) + | (((src_dst[4] >> i) & 0x1) << 4) + | (((src_dst[5] >> i) & 0x1) << 5) + | (((src_dst[6] >> i) & 0x1) << 6) + | (((src_dst[7] >> i) & 0x1) << 7); } + + memcpy(src_dst, dst8, 8 * sizeof(UInt64)); } -template -void transposeBytes(_T value, UInt64 * mx, UInt32 col) +template +void transposeBytes(T value, UInt64 * matrix, UInt32 col) { - UInt8 * mx8 = reinterpret_cast(mx); + UInt8 * matrix8 = reinterpret_cast(matrix); const UInt8 * value8 = reinterpret_cast(&value); - if constexpr (sizeof(_T) > 4) + if constexpr (sizeof(T) > 4) { - mx8[64 * 7 + col] = value8[7]; - mx8[64 * 6 + col] = value8[6]; - mx8[64 * 5 + col] = value8[5]; - mx8[64 * 4 + col] = value8[4]; + matrix8[64 * 7 + col] = value8[7]; + matrix8[64 * 6 + col] = value8[6]; + matrix8[64 * 5 + col] = value8[5]; + matrix8[64 * 4 + col] = value8[4]; } - if constexpr (sizeof(_T) > 2) + if constexpr (sizeof(T) > 2) { - mx8[64 * 3 + col] = value8[3]; - mx8[64 * 2 + col] = value8[2]; + matrix8[64 * 3 + col] = value8[3]; + matrix8[64 * 2 + col] = value8[2]; } - if constexpr (sizeof(_T) > 1) - mx8[64 * 1 + col] = value8[1]; + if constexpr (sizeof(T) > 1) + matrix8[64 * 1 + col] = value8[1]; - mx8[64 * 0 + col] = value8[0]; + matrix8[64 * 0 + col] = value8[0]; } -template -void revTransposeBytes(const UInt64 * mx, UInt32 col, _T & value) +template +void reverseTransposeBytes(const UInt64 * matrix, UInt32 col, T & value) { - auto * mx8 = reinterpret_cast(mx); + auto * matrix8 = reinterpret_cast(matrix); - if constexpr (sizeof(_T) > 4) + if constexpr (sizeof(T) > 4) { - value |= UInt64(mx8[64 * 7 + col]) << (8 * 7); - value |= UInt64(mx8[64 * 6 + col]) << (8 * 6); - value |= UInt64(mx8[64 * 5 + col]) << (8 * 5); - value |= UInt64(mx8[64 * 4 + col]) << (8 * 4); + value |= UInt64(matrix8[64 * 7 + col]) << (8 * 7); + value |= UInt64(matrix8[64 * 6 + col]) << (8 * 6); + value |= UInt64(matrix8[64 * 5 + col]) << (8 * 5); + value |= UInt64(matrix8[64 * 4 + col]) << (8 * 4); } - if constexpr (sizeof(_T) > 2) + if constexpr (sizeof(T) > 2) { - value |= UInt32(mx8[64 * 3 + col]) << (8 * 3); - value |= UInt32(mx8[64 * 2 + col]) << (8 * 2); + value |= UInt32(matrix8[64 * 3 + col]) << (8 * 3); + value |= UInt32(matrix8[64 * 2 + col]) << (8 * 2); } - if constexpr (sizeof(_T) > 1) - value |= UInt32(mx8[64 * 1 + col]) << (8 * 1); + if constexpr (sizeof(T) > 1) + value |= UInt32(matrix8[64 * 1 + col]) << (8 * 1); - value |= UInt32(mx8[col]); + value |= UInt32(matrix8[col]); +} + + +template +void load(const char * src, T * buf, UInt32 tail = 64) +{ + memcpy(buf, src, tail * sizeof(T)); +} + +template +void store(const T * buf, char * dst, UInt32 tail = 64) +{ + memcpy(dst, buf, tail * sizeof(T)); +} + +template +void clear(T * buf) +{ + for (UInt32 i = 0; i < 64; ++i) + buf[i] = 0; } /// UIntX[64] -> UInt64[N] transposed matrix, N <= X -template -void transpose(const char * src, char * dst, UInt32 num_bits, UInt32 tail = 64) +template +void transpose(const T * src, char * dst, UInt32 num_bits, UInt32 tail = 64) { UInt32 full_bytes = num_bits / 8; UInt32 part_bits = num_bits % 8; - UInt64 mx[64] = {}; - const char * ptr = src; - for (UInt32 col = 0; col < tail; ++col, ptr += sizeof(_T)) + UInt64 matrix[64] = {}; + for (UInt32 col = 0; col < tail; ++col) + transposeBytes(src[col], matrix, col); + + if constexpr (full) { - _T value = unalignedLoad<_T>(ptr); - transposeBytes(value, mx, col); + UInt64 * matrix_line = matrix; + for (UInt32 byte = 0; byte < full_bytes; ++byte, matrix_line += 8) + transpose64x8(matrix_line); } UInt32 full_size = sizeof(UInt64) * (num_bits - part_bits); - memcpy(dst, mx, full_size); + memcpy(dst, matrix, full_size); dst += full_size; /// transpose only partially filled last byte if (part_bits) { - UInt64 * partial = &mx[full_bytes * 8]; - UInt64 res[8] = {}; - transpose64x8(partial, res, part_bits); - memcpy(dst, res, part_bits * sizeof(UInt64)); + UInt64 * matrix_line = &matrix[full_bytes * 8]; + transpose64x8(matrix_line); + memcpy(dst, matrix_line, part_bits * sizeof(UInt64)); } } /// UInt64[N] transposed matrix -> UIntX[64] -template , Int64, UInt64>> -void revTranspose(const char * src, char * dst, UInt32 num_bits, _MinMaxT min, _MinMaxT max [[maybe_unused]], UInt32 tail = 64) +template +void reverseTranspose(const char * src, T * buf, UInt32 num_bits, UInt32 tail = 64) { - UInt64 mx[64] = {}; - memcpy(mx, src, num_bits * sizeof(UInt64)); + UInt64 matrix[64] = {}; + memcpy(matrix, src, num_bits * sizeof(UInt64)); UInt32 full_bytes = num_bits / 8; UInt32 part_bits = num_bits % 8; - UInt64 * partial = &mx[full_bytes * 8]; + + if constexpr (full) + { + UInt64 * matrix_line = matrix; + for (UInt32 byte = 0; byte < full_bytes; ++byte, matrix_line += 8) + reverseTranspose64x8(matrix_line); + } if (part_bits) { - UInt64 res[8] = {}; - revTranspose64x8(partial, res, part_bits); - memcpy(partial, res, 8 * sizeof(UInt64)); + UInt64 * matrix_line = &matrix[full_bytes * 8]; + reverseTranspose64x8(matrix_line); } - _T upper_min = 0; - if (num_bits < 64) - upper_min = UInt64(min) >> num_bits << num_bits; + clear(buf); + for (UInt32 col = 0; col < tail; ++col) + reverseTransposeBytes(matrix, col, buf[col]); +} - _T buf[64] = {}; - - if constexpr (std::is_signed_v<_T>) +template , Int64, UInt64>> +void restoreUpperBits(T * buf, T upper_min, T upper_max [[maybe_unused]], T sign_bit [[maybe_unused]], UInt32 tail = 64) +{ + if constexpr (std::is_signed_v) { /// Restore some data as negatives and others as positives - if (min < 0 && max >= 0 && num_bits < 64) + if (sign_bit) { - _T sign_bit = 1ull << (num_bits - 1); - _T upper_max = UInt64(max) >> num_bits << num_bits; - for (UInt32 col = 0; col < tail; ++col) { - _T & value = buf[col]; - revTransposeBytes(mx, col, value); + T & value = buf[col]; if (value & sign_bit) value |= upper_min; @@ -250,20 +280,12 @@ void revTranspose(const char * src, char * dst, UInt32 num_bits, _MinMaxT min, _ value |= upper_max; } - memcpy(dst, buf, tail * sizeof(_T)); return; } } for (UInt32 col = 0; col < tail; ++col) - { - _T & value = buf[col]; - revTransposeBytes(mx, col, value); - - value |= upper_min; - } - - memcpy(dst, buf, tail * sizeof(_T)); + buf[col] |= upper_min; } @@ -289,16 +311,16 @@ UInt32 getValuableBitsNumber(Int64 min, Int64 max) } -template -void findMinMax(const char * src, UInt32 src_size, _T & min, _T & max) +template +void findMinMax(const char * src, UInt32 src_size, T & min, T & max) { - min = unalignedLoad<_T>(src); - max = unalignedLoad<_T>(src); + min = unalignedLoad(src); + max = unalignedLoad(src); const char * end = src + src_size; - for (; src < end; src += sizeof(_T)) + for (; src < end; src += sizeof(T)) { - auto current = unalignedLoad<_T>(src); + auto current = unalignedLoad(src); if (current < min) min = current; if (current > max) @@ -306,24 +328,27 @@ void findMinMax(const char * src, UInt32 src_size, _T & min, _T & max) } } -template + +using Variant = CompressionCodecT64::Variant; + +template UInt32 compressData(const char * src, UInt32 bytes_size, char * dst) { - using MinMaxType = std::conditional_t, Int64, UInt64>; + using MinMaxType = std::conditional_t, Int64, UInt64>; - const UInt32 mx_size = 64; - const UInt32 header_size = 2 * sizeof(UInt64); + static constexpr const UInt32 matrix_size = 64; + static constexpr const UInt32 header_size = 2 * sizeof(UInt64); - if (bytes_size % sizeof(_T)) - throw Exception("Cannot compress, data size " + toString(bytes_size) + " is not multiplier of " + toString(sizeof(_T)), + if (bytes_size % sizeof(T)) + throw Exception("Cannot compress, data size " + toString(bytes_size) + " is not multiplier of " + toString(sizeof(T)), ErrorCodes::CANNOT_COMPRESS); - UInt32 src_size = bytes_size / sizeof(_T); - UInt32 num_full = src_size / mx_size; - UInt32 tail = src_size % mx_size; + UInt32 src_size = bytes_size / sizeof(T); + UInt32 num_full = src_size / matrix_size; + UInt32 tail = src_size % matrix_size; - _T min, max; - findMinMax<_T>(src, bytes_size, min, max); + T min, max; + findMinMax(src, bytes_size, min, max); MinMaxType min64 = min; MinMaxType max64 = max; @@ -338,11 +363,13 @@ UInt32 compressData(const char * src, UInt32 bytes_size, char * dst) if (!num_bits) return header_size; - UInt32 src_shift = sizeof(_T) * mx_size; + T buf[matrix_size]; + UInt32 src_shift = sizeof(T) * matrix_size; UInt32 dst_shift = sizeof(UInt64) * num_bits; for (UInt32 i = 0; i < num_full; ++i) { - transpose<_T>(src, dst, num_bits); + load(src, buf, matrix_size); + transpose(buf, dst, num_bits); src += src_shift; dst += dst_shift; } @@ -351,29 +378,31 @@ UInt32 compressData(const char * src, UInt32 bytes_size, char * dst) if (tail) { - transpose<_T>(src, dst, num_bits, tail); + load(src, buf, tail); + transpose(buf, dst, num_bits, tail); dst_bytes += dst_shift; } return header_size + dst_bytes; } -template +template void decompressData(const char * src, UInt32 bytes_size, char * dst, UInt32 uncompressed_size) { - using MinMaxType = std::conditional_t, Int64, UInt64>; + using MinMaxType = std::conditional_t, Int64, UInt64>; - const UInt32 header_size = 2 * sizeof(UInt64); + static constexpr const UInt32 matrix_size = 64; + static constexpr const UInt32 header_size = 2 * sizeof(UInt64); if (bytes_size < header_size) throw Exception("Cannot decompress, data size " + toString(bytes_size) + " is less then T64 header", ErrorCodes::CANNOT_DECOMPRESS); - if (uncompressed_size % sizeof(_T)) + if (uncompressed_size % sizeof(T)) throw Exception("Cannot decompress, unexpected uncompressed size " + toString(uncompressed_size), ErrorCodes::CANNOT_DECOMPRESS); - UInt64 num_elements = uncompressed_size / sizeof(_T); + UInt64 num_elements = uncompressed_size / sizeof(T); MinMaxType min; MinMaxType max; @@ -388,60 +417,101 @@ void decompressData(const char * src, UInt32 bytes_size, char * dst, UInt32 unco UInt32 num_bits = getValuableBitsNumber(min, max); if (!num_bits) { - _T min_value = min; - for (UInt32 i = 0; i < num_elements; ++i, dst += sizeof(_T)) - unalignedStore(dst, min_value); + T min_value = min; + for (UInt32 i = 0; i < num_elements; ++i, dst += sizeof(T)) + unalignedStore(dst, min_value); return; } UInt32 src_shift = sizeof(UInt64) * num_bits; - UInt32 dst_shift = sizeof(_T) * 64; + UInt32 dst_shift = sizeof(T) * matrix_size; if (!bytes_size || bytes_size % src_shift) throw Exception("Cannot decompress, data size " + toString(bytes_size) + " is not multiplier of " + toString(src_shift), ErrorCodes::CANNOT_DECOMPRESS); UInt32 num_full = bytes_size / src_shift; - UInt32 tail = num_elements % 64; + UInt32 tail = num_elements % matrix_size; if (tail) --num_full; + T upper_min = 0; + T upper_max [[maybe_unused]] = 0; + T sign_bit [[maybe_unused]] = 0; + if (num_bits < 64) + upper_min = UInt64(min) >> num_bits << num_bits; + + if constexpr (std::is_signed_v) + { + if (min < 0 && max >= 0 && num_bits < 64) + { + sign_bit = 1ull << (num_bits - 1); + upper_max = UInt64(max) >> num_bits << num_bits; + } + } + + T buf[matrix_size]; for (UInt32 i = 0; i < num_full; ++i) { - revTranspose<_T>(src, dst, num_bits, min, max); + reverseTranspose(src, buf, num_bits); + restoreUpperBits(buf, upper_min, upper_max, sign_bit); + store(buf, dst, matrix_size); src += src_shift; dst += dst_shift; } if (tail) - revTranspose<_T>(src, dst, num_bits, min, max, tail); + { + reverseTranspose(src, buf, num_bits, tail); + restoreUpperBits(buf, upper_min, upper_max, sign_bit, tail); + store(buf, dst, tail); + } +} + +template +UInt32 compressData(const char * src, UInt32 src_size, char * dst, Variant variant) +{ + if (variant == Variant::Bit) + return compressData(src, src_size, dst); + return compressData(src, src_size, dst); +} + +template +void decompressData(const char * src, UInt32 src_size, char * dst, UInt32 uncompressed_size, Variant variant) +{ + if (variant == Variant::Bit) + decompressData(src, src_size, dst, uncompressed_size); + else + decompressData(src, src_size, dst, uncompressed_size); } } + UInt32 CompressionCodecT64::doCompressData(const char * src, UInt32 src_size, char * dst) const { - memcpy(dst, &type_idx, 1); + UInt8 cookie = static_cast(type_idx) | (static_cast(variant) << 7); + memcpy(dst, &cookie, 1); dst += 1; switch (baseType(type_idx)) { case TypeIndex::Int8: - return 1 + compressData(src, src_size, dst); + return 1 + compressData(src, src_size, dst, variant); case TypeIndex::Int16: - return 1 + compressData(src, src_size, dst); + return 1 + compressData(src, src_size, dst, variant); case TypeIndex::Int32: - return 1 + compressData(src, src_size, dst); + return 1 + compressData(src, src_size, dst, variant); case TypeIndex::Int64: - return 1 + compressData(src, src_size, dst); + return 1 + compressData(src, src_size, dst, variant); case TypeIndex::UInt8: - return 1 + compressData(src, src_size, dst); + return 1 + compressData(src, src_size, dst, variant); case TypeIndex::UInt16: - return 1 + compressData(src, src_size, dst); + return 1 + compressData(src, src_size, dst, variant); case TypeIndex::UInt32: - return 1 + compressData(src, src_size, dst); + return 1 + compressData(src, src_size, dst, variant); case TypeIndex::UInt64: - return 1 + compressData(src, src_size, dst); + return 1 + compressData(src, src_size, dst, variant); default: break; } @@ -454,32 +524,31 @@ void CompressionCodecT64::doDecompressData(const char * src, UInt32 src_size, ch if (!src_size) throw Exception("Connot decompress with T64", ErrorCodes::CANNOT_DECOMPRESS); - UInt8 saved_type_id = unalignedLoad(src); + UInt8 cookie = unalignedLoad(src); src += 1; src_size -= 1; - TypeIndex actual_type_id = type_idx; - if (actual_type_id == TypeIndex::Nothing) - actual_type_id = static_cast(saved_type_id); + auto saved_variant = static_cast(cookie >> 7); + auto saved_type_id = static_cast(cookie & 0x7F); - switch (baseType(actual_type_id)) + switch (baseType(saved_type_id)) { case TypeIndex::Int8: - return decompressData(src, src_size, dst, uncompressed_size); + return decompressData(src, src_size, dst, uncompressed_size, saved_variant); case TypeIndex::Int16: - return decompressData(src, src_size, dst, uncompressed_size); + return decompressData(src, src_size, dst, uncompressed_size, saved_variant); case TypeIndex::Int32: - return decompressData(src, src_size, dst, uncompressed_size); + return decompressData(src, src_size, dst, uncompressed_size, saved_variant); case TypeIndex::Int64: - return decompressData(src, src_size, dst, uncompressed_size); + return decompressData(src, src_size, dst, uncompressed_size, saved_variant); case TypeIndex::UInt8: - return decompressData(src, src_size, dst, uncompressed_size); + return decompressData(src, src_size, dst, uncompressed_size, saved_variant); case TypeIndex::UInt16: - return decompressData(src, src_size, dst, uncompressed_size); + return decompressData(src, src_size, dst, uncompressed_size, saved_variant); case TypeIndex::UInt32: - return decompressData(src, src_size, dst, uncompressed_size); + return decompressData(src, src_size, dst, uncompressed_size, saved_variant); case TypeIndex::UInt64: - return decompressData(src, src_size, dst, uncompressed_size); + return decompressData(src, src_size, dst, uncompressed_size, saved_variant); default: break; } @@ -506,13 +575,33 @@ void registerCodecT64(CompressionCodecFactory & factory) { auto reg_func = [&](const ASTPtr & arguments, DataTypePtr type) -> CompressionCodecPtr { + Variant variant = Variant::Byte; + if (arguments && !arguments->children.empty()) - throw Exception("T64 codec should not have parameters", ErrorCodes::ILLEGAL_SYNTAX_FOR_CODEC_TYPE); + { + if (arguments->children.size() > 1) + throw Exception("T64 support zero or one parameter, given " + std::to_string(arguments->children.size()), + ErrorCodes::ILLEGAL_SYNTAX_FOR_CODEC_TYPE); + + const auto children = arguments->children; + const auto * literal = children[0]->as(); + if (!literal) + throw Exception("Wrong modification for T64. Expected: 'bit', 'byte')", + ErrorCodes::ILLEGAL_CODEC_PARAMETER); + String name = literal->value.safeGet(); + + if (name == "byte") + variant = Variant::Byte; + else if (name == "bit") + variant = Variant::Bit; + else + throw Exception("Wrong modification for T64: " + name, ErrorCodes::ILLEGAL_CODEC_PARAMETER); + } auto type_idx = typeIdx(type); if (type && type_idx == TypeIndex::Nothing) throw Exception("T64 codec is not supported for specified type", ErrorCodes::ILLEGAL_SYNTAX_FOR_CODEC_TYPE); - return std::make_shared(type_idx); + return std::make_shared(type_idx, variant); }; factory.registerCompressionCodecWithType("T64", codecId(), reg_func); diff --git a/dbms/src/Compression/CompressionCodecT64.h b/dbms/src/Compression/CompressionCodecT64.h index 6425705b73f..ec720e14c78 100644 --- a/dbms/src/Compression/CompressionCodecT64.h +++ b/dbms/src/Compression/CompressionCodecT64.h @@ -6,18 +6,35 @@ namespace DB { +/// Get 64 integer valuses, makes 64x64 bit matrix, transpose it and crop unused bits (most significant zeroes). +/// In example, if we have UInt8 with only 0 and 1 inside 64xUInt8 would be compressed into 1xUInt64. +/// It detects unused bits by calculating min and max values of data part, saving them in header in compression phase. +/// There's a special case with signed integers parts with crossing zero data. Here it stores one more bit to detect sign of value. class CompressionCodecT64 : public ICompressionCodec { public: static constexpr UInt32 HEADER_SIZE = 1 + 2 * sizeof(UInt64); static constexpr UInt32 MAX_COMPRESSED_BLOCK_SIZE = sizeof(UInt64) * 64; - CompressionCodecT64(TypeIndex type_idx_) + /// There're 2 compression variants: + /// Byte - transpose bit matrix by bytes (only the last not full byte is transposed by bits). It's default. + /// Bits - full bit-transpose of the bit matrix. It uses more resources and leads to better compression with ZSTD (but worse with LZ4). + enum class Variant + { + Byte, + Bit + }; + + CompressionCodecT64(TypeIndex type_idx_, Variant variant_) : type_idx(type_idx_) + , variant(variant_) {} UInt8 getMethodByte() const override; - String getCodecDesc() const override { return "T64"; } + String getCodecDesc() const override + { + return String("T64") + ((variant == Variant::Byte) ? "" : "(\'bit\')"); + } void useInfoAboutType(DataTypePtr data_type) override; @@ -33,6 +50,7 @@ protected: private: TypeIndex type_idx; + Variant variant; }; } diff --git a/dbms/src/Compression/LZ4_decompress_faster.cpp b/dbms/src/Compression/LZ4_decompress_faster.cpp index 387650d3dcc..65ffdb2173b 100644 --- a/dbms/src/Compression/LZ4_decompress_faster.cpp +++ b/dbms/src/Compression/LZ4_decompress_faster.cpp @@ -154,7 +154,7 @@ inline void copyOverlap8(UInt8 * op, const UInt8 *& match, const size_t offset) */ inline void copyOverlap8Shuffle(UInt8 * op, const UInt8 *& match, const size_t offset) { -#ifdef __SSSE3__ +#if defined(__SSSE3__) && !defined(MEMORY_SANITIZER) static constexpr UInt8 __attribute__((__aligned__(8))) masks[] = { @@ -200,7 +200,7 @@ inline void copyOverlap8Shuffle(UInt8 * op, const UInt8 *& match, const size_t o 0, 1, 2, 3, 4, 5, 6, 0, }; - unalignedStore(op, vtbl1_u8(unalignedLoad(match), unalignedLoad(masks + 8 * offset))); + unalignedStore(op, vtbl1_u8(unalignedLoad(match), unalignedLoad(masks + 8 * offset))); match += masks[offset]; } @@ -268,7 +268,7 @@ inline void copyOverlap16(UInt8 * op, const UInt8 *& match, const size_t offset) inline void copyOverlap16Shuffle(UInt8 * op, const UInt8 *& match, const size_t offset) { -#ifdef __SSSE3__ +#if defined(__SSSE3__) && !defined(MEMORY_SANITIZER) static constexpr UInt8 __attribute__((__aligned__(16))) masks[] = { @@ -328,10 +328,10 @@ inline void copyOverlap16Shuffle(UInt8 * op, const UInt8 *& match, const size_t 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, }; - unalignedStore(op, + unalignedStore(op, vtbl2_u8(unalignedLoad(match), unalignedLoad(masks + 16 * offset))); - unalignedStore(op + 8, + unalignedStore(op + 8, vtbl2_u8(unalignedLoad(match), unalignedLoad(masks + 16 * offset + 8))); match += masks[offset]; diff --git a/dbms/src/Compression/tests/CMakeLists.txt b/dbms/src/Compression/tests/CMakeLists.txt index 50f212f18c3..3cfc0ccb7dc 100644 --- a/dbms/src/Compression/tests/CMakeLists.txt +++ b/dbms/src/Compression/tests/CMakeLists.txt @@ -1,5 +1,5 @@ add_executable (compressed_buffer compressed_buffer.cpp) -target_link_libraries (compressed_buffer PRIVATE clickhouse_compression clickhouse_common_io) +target_link_libraries (compressed_buffer PRIVATE dbms) add_executable (cached_compressed_read_buffer cached_compressed_read_buffer.cpp) -target_link_libraries (cached_compressed_read_buffer PRIVATE clickhouse_compression clickhouse_common_io) +target_link_libraries (cached_compressed_read_buffer PRIVATE dbms) diff --git a/dbms/src/Compression/tests/gtest_compressionCodec.cpp b/dbms/src/Compression/tests/gtest_compressionCodec.cpp index e1413ccd7bd..96a70d46433 100644 --- a/dbms/src/Compression/tests/gtest_compressionCodec.cpp +++ b/dbms/src/Compression/tests/gtest_compressionCodec.cpp @@ -20,11 +20,6 @@ #include #include -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" -#pragma clang diagnostic ignored "-Wundef" -#endif #include using namespace DB; diff --git a/dbms/src/Core/Block.cpp b/dbms/src/Core/Block.cpp index 27b2cb81b09..9f8b66b1778 100644 --- a/dbms/src/Core/Block.cpp +++ b/dbms/src/Core/Block.cpp @@ -336,6 +336,7 @@ MutableColumns Block::mutateColumns() void Block::setColumns(MutableColumns && columns) { + /// TODO: assert if |columns| doesn't match |data|! size_t num_columns = data.size(); for (size_t i = 0; i < num_columns; ++i) data[i].column = std::move(columns[i]); @@ -344,6 +345,7 @@ void Block::setColumns(MutableColumns && columns) void Block::setColumns(const Columns & columns) { + /// TODO: assert if |columns| doesn't match |data|! size_t num_columns = data.size(); for (size_t i = 0; i < num_columns; ++i) data[i].column = columns[i]; @@ -368,6 +370,11 @@ Block Block::cloneWithColumns(const Columns & columns) const Block res; size_t num_columns = data.size(); + + if (num_columns != columns.size()) + throw Exception("Cannot clone block with columns because block has " + toString(num_columns) + " columns, " + "but " + toString(columns.size()) + " columns given.", ErrorCodes::LOGICAL_ERROR); + for (size_t i = 0; i < num_columns; ++i) res.insert({ columns[i], data[i].type, data[i].name }); @@ -472,7 +479,7 @@ static ReturnType checkBlockStructure(const Block & lhs, const Block & rhs, cons return on_error("Block structure mismatch in " + context_description + " stream: different columns:\n" + lhs.dumpStructure() + "\n" + rhs.dumpStructure(), ErrorCodes::BLOCKS_HAVE_DIFFERENT_STRUCTURE); - if (actual.column->isColumnConst() && expected.column->isColumnConst()) + if (isColumnConst(*actual.column) && isColumnConst(*expected.column)) { Field actual_value = static_cast(*actual.column).getField(); Field expected_value = static_cast(*expected.column).getField(); diff --git a/dbms/src/Core/DecimalComparison.h b/dbms/src/Core/DecimalComparison.h index 713f6a6e770..13cbfda32a3 100644 --- a/dbms/src/Core/DecimalComparison.h +++ b/dbms/src/Core/DecimalComparison.h @@ -167,8 +167,8 @@ private: if constexpr (_actual) { - bool c0_is_const = c0->isColumnConst(); - bool c1_is_const = c1->isColumnConst(); + bool c0_is_const = isColumnConst(*c0); + bool c1_is_const = isColumnConst(*c1); if (c0_is_const && c1_is_const) { diff --git a/dbms/src/Core/Defines.h b/dbms/src/Core/Defines.h index b8db4d64843..f611f9df04e 100644 --- a/dbms/src/Core/Defines.h +++ b/dbms/src/Core/Defines.h @@ -88,7 +88,7 @@ #define PLATFORM_NOT_SUPPORTED "The only supported platforms are x86_64 and AArch64, PowerPC (work in progress)" #if !defined(__x86_64__) && !defined(__aarch64__) && !defined(__PPC__) -// #error PLATFORM_NOT_SUPPORTED + #error PLATFORM_NOT_SUPPORTED #endif /// Check for presence of address sanitizer @@ -108,16 +108,26 @@ #define THREAD_SANITIZER 1 #endif +#if defined(__has_feature) + #if __has_feature(memory_sanitizer) + #define MEMORY_SANITIZER 1 + #endif +#elif defined(__MEMORY_SANITIZER__) + #define MEMORY_SANITIZER 1 +#endif + /// Explicitly allow undefined behaviour for certain functions. Use it as a function attribute. /// It is useful in case when compiler cannot see (and exploit) it, but UBSan can. /// Example: multiplication of signed integers with possibility of overflow when both sides are from user input. #if defined(__clang__) #define NO_SANITIZE_UNDEFINED __attribute__((__no_sanitize__("undefined"))) #define NO_SANITIZE_ADDRESS __attribute__((__no_sanitize__("address"))) + #define NO_SANITIZE_THREAD __attribute__((__no_sanitize__("thread"))) #else /// It does not work in GCC. GCC 7 cannot recognize this attribute and GCC 8 simply ignores it. #define NO_SANITIZE_UNDEFINED #define NO_SANITIZE_ADDRESS + #define NO_SANITIZE_THREAD #endif #if defined __GNUC__ && !defined __clang__ diff --git a/dbms/src/Core/ExternalTable.cpp b/dbms/src/Core/ExternalTable.cpp index 65bff362aa7..e1e059a3b63 100644 --- a/dbms/src/Core/ExternalTable.cpp +++ b/dbms/src/Core/ExternalTable.cpp @@ -160,7 +160,7 @@ void ExternalTablesHandler::handlePart(const Poco::Net::MessageHeader & header, /// Create table NamesAndTypesList columns = sample_block.getNamesAndTypesList(); - StoragePtr storage = StorageMemory::create(data.second, ColumnsDescription{columns}); + StoragePtr storage = StorageMemory::create("_external", data.second, ColumnsDescription{columns}); storage->startup(); context.addExternalTable(data.second, storage); BlockOutputStreamPtr output = storage->write(ASTPtr(), context); diff --git a/dbms/src/Core/Field.h b/dbms/src/Core/Field.h index 832b45cd6f8..156f272312b 100644 --- a/dbms/src/Core/Field.h +++ b/dbms/src/Core/Field.h @@ -717,8 +717,8 @@ class WriteBuffer; /// It is assumed that all elements of the array have the same type. void readBinary(Array & x, ReadBuffer & buf); -inline void readText(Array &, ReadBuffer &) { throw Exception("Cannot read Array.", ErrorCodes::NOT_IMPLEMENTED); } -inline void readQuoted(Array &, ReadBuffer &) { throw Exception("Cannot read Array.", ErrorCodes::NOT_IMPLEMENTED); } +[[noreturn]] inline void readText(Array &, ReadBuffer &) { throw Exception("Cannot read Array.", ErrorCodes::NOT_IMPLEMENTED); } +[[noreturn]] inline void readQuoted(Array &, ReadBuffer &) { throw Exception("Cannot read Array.", ErrorCodes::NOT_IMPLEMENTED); } /// It is assumed that all elements of the array have the same type. /// Also write size and type into buf. UInt64 and Int64 is written in variadic size form @@ -726,16 +726,16 @@ void writeBinary(const Array & x, WriteBuffer & buf); void writeText(const Array & x, WriteBuffer & buf); -inline void writeQuoted(const Array &, WriteBuffer &) { throw Exception("Cannot write Array quoted.", ErrorCodes::NOT_IMPLEMENTED); } +[[noreturn]] inline void writeQuoted(const Array &, WriteBuffer &) { throw Exception("Cannot write Array quoted.", ErrorCodes::NOT_IMPLEMENTED); } void readBinary(Tuple & x, ReadBuffer & buf); -inline void readText(Tuple &, ReadBuffer &) { throw Exception("Cannot read Tuple.", ErrorCodes::NOT_IMPLEMENTED); } -inline void readQuoted(Tuple &, ReadBuffer &) { throw Exception("Cannot read Tuple.", ErrorCodes::NOT_IMPLEMENTED); } +[[noreturn]] inline void readText(Tuple &, ReadBuffer &) { throw Exception("Cannot read Tuple.", ErrorCodes::NOT_IMPLEMENTED); } +[[noreturn]] inline void readQuoted(Tuple &, ReadBuffer &) { throw Exception("Cannot read Tuple.", ErrorCodes::NOT_IMPLEMENTED); } void writeBinary(const Tuple & x, WriteBuffer & buf); void writeText(const Tuple & x, WriteBuffer & buf); -inline void writeQuoted(const Tuple &, WriteBuffer &) { throw Exception("Cannot write Tuple quoted.", ErrorCodes::NOT_IMPLEMENTED); } +[[noreturn]] inline void writeQuoted(const Tuple &, WriteBuffer &) { throw Exception("Cannot write Tuple quoted.", ErrorCodes::NOT_IMPLEMENTED); } } diff --git a/dbms/src/Core/MySQLProtocol.cpp b/dbms/src/Core/MySQLProtocol.cpp index f727ae3df54..529aac27074 100644 --- a/dbms/src/Core/MySQLProtocol.cpp +++ b/dbms/src/Core/MySQLProtocol.cpp @@ -30,7 +30,7 @@ String PacketSender::packetToText(String payload) uint64_t readLengthEncodedNumber(std::istringstream & ss) { - char c; + char c{}; uint64_t buf = 0; ss.get(c); auto cc = static_cast(c); diff --git a/dbms/src/Core/Settings.h b/dbms/src/Core/Settings.h index fe65788656b..f49e09ba599 100644 --- a/dbms/src/Core/Settings.h +++ b/dbms/src/Core/Settings.h @@ -62,6 +62,7 @@ struct Settings : public SettingsCollection M(SettingSeconds, tcp_keep_alive_timeout, 0, "") \ M(SettingMilliseconds, queue_max_wait_ms, 5000, "The wait time in the request queue, if the number of concurrent requests exceeds the maximum.") \ M(SettingUInt64, poll_interval, DBMS_DEFAULT_POLL_INTERVAL, "Block at the query wait loop on the server for the specified number of seconds.") \ + M(SettingUInt64, idle_connection_timeout, 3600, "Close idle TCP connections after specified number of seconds.") \ M(SettingUInt64, distributed_connections_pool_size, DBMS_DEFAULT_DISTRIBUTED_CONNECTIONS_POOL_SIZE, "Maximum number of connections with one remote server in the pool.") \ M(SettingUInt64, connections_with_failover_max_tries, DBMS_CONNECTION_POOL_WITH_FAILOVER_DEFAULT_MAX_TRIES, "The maximum number of attempts to connect to replicas.") \ M(SettingBool, extremes, false, "Calculate minimums and maximums of the result columns. They can be output in JSON-formats.") \ @@ -104,12 +105,12 @@ struct Settings : public SettingsCollection M(SettingBool, optimize_skip_unused_shards, false, "Assumes that data is distributed by sharding_key. Optimization to skip unused shards if SELECT query filters by sharding_key.") \ \ M(SettingUInt64, merge_tree_min_rows_for_concurrent_read, (20 * 8192), "If at least as many lines are read from one file, the reading can be parallelized.") \ - M(SettingUInt64, merge_tree_min_bytes_for_concurrent_read, (100 * 1024 * 1024), "If at least as many bytes are read from one file, the reading can be parallelized.") \ + M(SettingUInt64, merge_tree_min_bytes_for_concurrent_read, (24 * 10 * 1024 * 1024), "If at least as many bytes are read from one file, the reading can be parallelized.") \ M(SettingUInt64, merge_tree_min_rows_for_seek, 0, "You can skip reading more than that number of rows at the price of one seek per file.") \ M(SettingUInt64, merge_tree_min_bytes_for_seek, 0, "You can skip reading more than that number of bytes at the price of one seek per file.") \ M(SettingUInt64, merge_tree_coarse_index_granularity, 8, "If the index segment can contain the required keys, divide it into as many parts and recursively check them.") \ - M(SettingUInt64, merge_tree_max_rows_to_use_cache, (1024 * 1024), "The maximum number of rows per request, to use the cache of uncompressed data. If the request is large, the cache is not used. (For large queries not to flush out the cache.)") \ - M(SettingUInt64, merge_tree_max_bytes_to_use_cache, (600 * 1024 * 1024), "The maximum number of rows per request, to use the cache of uncompressed data. If the request is large, the cache is not used. (For large queries not to flush out the cache.)") \ + M(SettingUInt64, merge_tree_max_rows_to_use_cache, (128 * 8192), "The maximum number of rows per request, to use the cache of uncompressed data. If the request is large, the cache is not used. (For large queries not to flush out the cache.)") \ + M(SettingUInt64, merge_tree_max_bytes_to_use_cache, (192 * 10 * 1024 * 1024), "The maximum number of rows per request, to use the cache of uncompressed data. If the request is large, the cache is not used. (For large queries not to flush out the cache.)") \ \ M(SettingBool, merge_tree_uniform_read_distribution, true, "Distribute read from MergeTree over threads evenly, ensuring stable average execution time of each thread within one read operation.") \ \ @@ -125,12 +126,14 @@ struct Settings : public SettingsCollection M(SettingUInt64, mark_cache_min_lifetime, 10000, "If the maximum size of mark_cache is exceeded, delete only records older than mark_cache_min_lifetime seconds.") \ \ M(SettingFloat, max_streams_to_max_threads_ratio, 1, "Allows you to use more sources than the number of threads - to more evenly distribute work across threads. It is assumed that this is a temporary solution, since it will be possible in the future to make the number of sources equal to the number of threads, but for each source to dynamically select available work for itself.") \ + M(SettingFloat, max_streams_multiplier_for_merge_tables, 5, "Ask more streams when reading from Merge table. Streams will be spread across tables that Merge table will use. This allows more even distribution of work across threads and especially helpful when merged tables differ in size.") \ \ M(SettingString, network_compression_method, "LZ4", "Allows you to select the method of data compression when writing.") \ \ M(SettingInt64, network_zstd_compression_level, 1, "Allows you to select the level of ZSTD compression.") \ \ M(SettingUInt64, priority, 0, "Priority of the query. 1 - the highest, higher value - lower priority; 0 - do not use priorities.") \ + M(SettingInt64, os_thread_priority, 0, "If non zero - set corresponding 'nice' value for query processing threads. Can be used to adjust query priority for OS scheduler.") \ \ M(SettingBool, log_queries, 0, "Log requests and write the log to the system table.") \ \ @@ -323,8 +326,10 @@ struct Settings : public SettingsCollection M(SettingBool, external_table_functions_use_nulls, true, "If it is set to true, external table functions will implicitly use Nullable type if needed. Otherwise NULLs will be substituted with default values. Currently supported only for 'mysql' table function.") \ M(SettingBool, allow_experimental_data_skipping_indices, false, "If it is set to true, data skipping indices can be used in CREATE TABLE/ALTER TABLE queries.") \ \ - M(SettingBool, allow_hyperscan, 1, "Allow functions that use Hyperscan library. Disable to avoid potentially long compilation times and excessive resource usage.") \ - M(SettingBool, allow_simdjson, 1, "Allow using simdjson library in 'JSON*' functions if AVX2 instructions are available. If disabled rapidjson will be used.") \ + M(SettingBool, experimental_use_processors, false, "Use processors pipeline.") \ + \ + M(SettingBool, allow_hyperscan, true, "Allow functions that use Hyperscan library. Disable to avoid potentially long compilation times and excessive resource usage.") \ + M(SettingBool, allow_simdjson, true, "Allow using simdjson library in 'JSON*' functions if AVX2 instructions are available. If disabled rapidjson will be used.") \ \ M(SettingUInt64, max_partitions_per_insert_block, 100, "Limit maximum number of partitions in single INSERTed block. Zero means unlimited. Throw exception if the block contains too many partitions. This setting is a safety threshold, because using large number of partitions is a common misconception.") diff --git a/dbms/src/Core/SettingsCommon.h b/dbms/src/Core/SettingsCommon.h index b30b5b50c68..08064096133 100644 --- a/dbms/src/Core/SettingsCommon.h +++ b/dbms/src/Core/SettingsCommon.h @@ -275,7 +275,7 @@ namespace details { static void serializeName(const StringRef & name, WriteBuffer & buf); static String deserializeName(ReadBuffer & buf); - static void throwNameNotFound(const StringRef & name); + [[noreturn]] static void throwNameNotFound(const StringRef & name); }; } diff --git a/dbms/src/Core/SortCursor.h b/dbms/src/Core/SortCursor.h index 5a49209cb71..3a2b64cd8b6 100644 --- a/dbms/src/Core/SortCursor.h +++ b/dbms/src/Core/SortCursor.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -47,26 +48,44 @@ struct SortCursorImpl reset(block); } + SortCursorImpl(const Columns & columns, const SortDescription & desc_, size_t order_ = 0) + : desc(desc_), sort_columns_size(desc.size()), order(order_), need_collation(desc.size()) + { + for (auto & column_desc : desc) + { + if (!column_desc.column_name.empty()) + throw Exception("SortDesctiption should contain column position if SortCursor was used without header.", + ErrorCodes::LOGICAL_ERROR); + } + reset(columns, {}); + } + bool empty() const { return rows == 0; } /// Set the cursor to the beginning of the new block. void reset(const Block & block) + { + reset(block.getColumns(), block); + } + + /// Set the cursor to the beginning of the new block. + void reset(const Columns & columns, const Block & block) { all_columns.clear(); sort_columns.clear(); - size_t num_columns = block.columns(); + size_t num_columns = columns.size(); for (size_t j = 0; j < num_columns; ++j) - all_columns.push_back(block.safeGetByPosition(j).column.get()); + all_columns.push_back(columns[j].get()); for (size_t j = 0, size = desc.size(); j < size; ++j) { - size_t column_number = !desc[j].column_name.empty() - ? block.getPositionByName(desc[j].column_name) - : desc[j].column_number; - - sort_columns.push_back(block.safeGetByPosition(column_number).column.get()); + auto & column_desc = desc[j]; + size_t column_number = !column_desc.column_name.empty() + ? block.getPositionByName(column_desc.column_name) + : column_desc.column_number; + sort_columns.push_back(columns[column_number].get()); need_collation[j] = desc[j].collator != nullptr && typeid_cast(sort_columns.back()); /// TODO Nullable(String) has_collation |= need_collation[j]; diff --git a/dbms/src/Core/Types.h b/dbms/src/Core/Types.h index 3541eaf296a..75c7cbaff66 100644 --- a/dbms/src/Core/Types.h +++ b/dbms/src/Core/Types.h @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include namespace DB diff --git a/dbms/src/DataStreams/AddingDefaultsBlockInputStream.cpp b/dbms/src/DataStreams/AddingDefaultsBlockInputStream.cpp index 6b959cbc05b..168dea36b36 100644 --- a/dbms/src/DataStreams/AddingDefaultsBlockInputStream.cpp +++ b/dbms/src/DataStreams/AddingDefaultsBlockInputStream.cpp @@ -187,7 +187,7 @@ MutableColumnPtr AddingDefaultsBlockInputStream::mixColumns(const ColumnWithType { if (defaults_mask[i]) { - if (col_defaults.column->isColumnConst()) + if (isColumnConst(*col_defaults.column)) column_mixed->insert((*col_defaults.column)[i]); else column_mixed->insertFrom(*col_defaults.column, i); diff --git a/dbms/src/DataStreams/BlockIO.h b/dbms/src/DataStreams/BlockIO.h index 913dbdbe5c7..e7c1d41e845 100644 --- a/dbms/src/DataStreams/BlockIO.h +++ b/dbms/src/DataStreams/BlockIO.h @@ -4,6 +4,8 @@ #include +#include + namespace DB { @@ -25,6 +27,8 @@ struct BlockIO BlockOutputStreamPtr out; BlockInputStreamPtr in; + QueryPipeline pipeline; + /// Callbacks for query logging could be set here. std::function finish_callback; std::function exception_callback; @@ -54,6 +58,7 @@ struct BlockIO process_list_entry = rhs.process_list_entry; in = rhs.in; out = rhs.out; + pipeline = rhs.pipeline; finish_callback = rhs.finish_callback; exception_callback = rhs.exception_callback; diff --git a/dbms/src/DataStreams/BlockStreamProfileInfo.cpp b/dbms/src/DataStreams/BlockStreamProfileInfo.cpp index 0277c19ae42..5f83f419861 100644 --- a/dbms/src/DataStreams/BlockStreamProfileInfo.cpp +++ b/dbms/src/DataStreams/BlockStreamProfileInfo.cpp @@ -71,6 +71,9 @@ void BlockStreamProfileInfo::update(Block & block) void BlockStreamProfileInfo::collectInfosForStreamsWithName(const char * name, BlockStreamProfileInfos & res) const { + if (!parent) + return; + if (parent->getName() == name) { res.push_back(this); diff --git a/dbms/src/DataStreams/BlockStreamProfileInfo.h b/dbms/src/DataStreams/BlockStreamProfileInfo.h index ebc83204451..6b60fa95e24 100644 --- a/dbms/src/DataStreams/BlockStreamProfileInfo.h +++ b/dbms/src/DataStreams/BlockStreamProfileInfo.h @@ -50,6 +50,13 @@ struct BlockStreamProfileInfo /// If skip_block_size_info if true, then rows, bytes and block fields are ignored. void setFrom(const BlockStreamProfileInfo & rhs, bool skip_block_size_info); + /// Only for Processors. + void setRowsBeforeLimit(size_t rows_before_limit_) + { + applied_limit = true; + rows_before_limit = rows_before_limit_; + } + private: void calculateRowsBeforeLimit() const; diff --git a/dbms/src/DataStreams/ConvertingBlockInputStream.cpp b/dbms/src/DataStreams/ConvertingBlockInputStream.cpp index 4c78aeb7ce5..0ab250ac7ee 100644 --- a/dbms/src/DataStreams/ConvertingBlockInputStream.cpp +++ b/dbms/src/DataStreams/ConvertingBlockInputStream.cpp @@ -60,7 +60,7 @@ ConvertingBlockInputStream::ConvertingBlockInputStream( if (input_header.has(res_elem.name)) conversion[result_col_num] = input_header.getPositionByName(res_elem.name); else - throw Exception("Cannot find column " + backQuoteIfNeed(res_elem.name) + " in source stream", + throw Exception("Cannot find column " + backQuote(res_elem.name) + " in source stream", ErrorCodes::THERE_IS_NO_COLUMN); break; } @@ -69,9 +69,9 @@ ConvertingBlockInputStream::ConvertingBlockInputStream( /// Check constants. - if (res_elem.column->isColumnConst()) + if (isColumnConst(*res_elem.column)) { - if (!src_elem.column->isColumnConst()) + if (!isColumnConst(*src_elem.column)) throw Exception("Cannot convert column " + backQuoteIfNeed(res_elem.name) + " because it is non constant in source stream but must be constant in result", ErrorCodes::BLOCKS_HAVE_DIFFERENT_STRUCTURE); @@ -103,7 +103,7 @@ Block ConvertingBlockInputStream::readImpl() ColumnPtr converted = castColumnWithDiagnostic(src_elem, res_elem, context); - if (src_elem.column->isColumnConst() && !res_elem.column->isColumnConst()) + if (isColumnConst(*src_elem.column) && !isColumnConst(*res_elem.column)) converted = converted->convertToFullColumnIfConst(); res_elem.column = std::move(converted); diff --git a/dbms/src/DataStreams/DistinctBlockInputStream.cpp b/dbms/src/DataStreams/DistinctBlockInputStream.cpp index 644d8fef89b..77ea87f1be3 100644 --- a/dbms/src/DataStreams/DistinctBlockInputStream.cpp +++ b/dbms/src/DataStreams/DistinctBlockInputStream.cpp @@ -112,7 +112,7 @@ ColumnRawPtrs DistinctBlockInputStream::getKeyColumns(const Block & block) const : block.getByName(columns_names[i]).column; /// Ignore all constant columns. - if (!column->isColumnConst()) + if (!isColumnConst(*column)) column_ptrs.emplace_back(column.get()); } diff --git a/dbms/src/DataStreams/DistinctSortedBlockInputStream.cpp b/dbms/src/DataStreams/DistinctSortedBlockInputStream.cpp index ca38637ff1d..2b715f64823 100644 --- a/dbms/src/DataStreams/DistinctSortedBlockInputStream.cpp +++ b/dbms/src/DataStreams/DistinctSortedBlockInputStream.cpp @@ -131,7 +131,7 @@ ColumnRawPtrs DistinctSortedBlockInputStream::getKeyColumns(const Block & block) : block.getByName(columns_names[i]).column; /// Ignore all constant columns. - if (!column->isColumnConst()) + if (!isColumnConst(*column)) column_ptrs.emplace_back(column.get()); } diff --git a/dbms/src/DataStreams/FilterBlockInputStream.cpp b/dbms/src/DataStreams/FilterBlockInputStream.cpp index 53410c024a3..63782890331 100644 --- a/dbms/src/DataStreams/FilterBlockInputStream.cpp +++ b/dbms/src/DataStreams/FilterBlockInputStream.cpp @@ -112,7 +112,7 @@ Block FilterBlockInputStream::readImpl() size_t first_non_constant_column = 0; for (size_t i = 0; i < columns; ++i) { - if (!res.safeGetByPosition(i).column->isColumnConst()) + if (!isColumnConst(*res.safeGetByPosition(i).column)) { first_non_constant_column = i; @@ -165,7 +165,7 @@ Block FilterBlockInputStream::readImpl() if (i == first_non_constant_column) continue; - if (current_column.column->isColumnConst()) + if (isColumnConst(*current_column.column)) current_column.column = current_column.column->cut(0, filtered_rows); else current_column.column = current_column.column->filter(*filter_and_holder.data, -1); diff --git a/dbms/src/DataStreams/IBlockInputStream.cpp b/dbms/src/DataStreams/IBlockInputStream.cpp index 11aeaf62ffd..38553e5183d 100644 --- a/dbms/src/DataStreams/IBlockInputStream.cpp +++ b/dbms/src/DataStreams/IBlockInputStream.cpp @@ -144,7 +144,7 @@ void IBlockInputStream::updateExtremes(Block & block) { const ColumnPtr & src = block.safeGetByPosition(i).column; - if (src->isColumnConst()) + if (isColumnConst(*src)) { /// Equal min and max. extremes_columns[i] = src->cloneResized(2); @@ -171,7 +171,7 @@ void IBlockInputStream::updateExtremes(Block & block) { ColumnPtr & old_extremes = extremes.safeGetByPosition(i).column; - if (old_extremes->isColumnConst()) + if (isColumnConst(*old_extremes)) continue; Field min_value = (*old_extremes)[0]; diff --git a/dbms/src/DataStreams/LimitBlockInputStream.cpp b/dbms/src/DataStreams/LimitBlockInputStream.cpp index b1b8f5c95d1..1348a223000 100644 --- a/dbms/src/DataStreams/LimitBlockInputStream.cpp +++ b/dbms/src/DataStreams/LimitBlockInputStream.cpp @@ -23,7 +23,7 @@ Block LimitBlockInputStream::readImpl() Block res; UInt64 rows = 0; - /// pos - how many lines were read, including the last read block + /// pos - how many rows were read, including the last read block if (pos >= offset + limit) { @@ -46,7 +46,7 @@ Block LimitBlockInputStream::readImpl() pos += rows; } while (pos <= offset); - /// give away the whole block + /// return the whole block if (pos >= offset + rows && pos <= offset + limit) return res; @@ -61,7 +61,7 @@ Block LimitBlockInputStream::readImpl() static_cast(limit) + static_cast(offset) - static_cast(pos) + static_cast(rows))); for (size_t i = 0; i < res.columns(); ++i) - res.safeGetByPosition(i).column = res.safeGetByPosition(i).column->cut(start, length); + res.getByPosition(i).column = res.getByPosition(i).column->cut(start, length); // TODO: we should provide feedback to child-block, so it will know how many rows are actually consumed. // It's crucial for streaming engines like Kafka. diff --git a/dbms/src/DataStreams/LimitByBlockInputStream.cpp b/dbms/src/DataStreams/LimitByBlockInputStream.cpp index 93f1ce83ae8..55f3dae02bd 100644 --- a/dbms/src/DataStreams/LimitByBlockInputStream.cpp +++ b/dbms/src/DataStreams/LimitByBlockInputStream.cpp @@ -71,7 +71,7 @@ ColumnRawPtrs LimitByBlockInputStream::getKeyColumns(Block & block) const auto & column = block.getByName(name).column; /// Ignore all constant columns. - if (!column->isColumnConst()) + if (!isColumnConst(*column)) column_ptrs.emplace_back(column.get()); } diff --git a/dbms/src/DataStreams/OneBlockInputStream.h b/dbms/src/DataStreams/OneBlockInputStream.h index 3f1da34fcd8..168053b4fb3 100644 --- a/dbms/src/DataStreams/OneBlockInputStream.h +++ b/dbms/src/DataStreams/OneBlockInputStream.h @@ -12,7 +12,7 @@ namespace DB class OneBlockInputStream : public IBlockInputStream { public: - OneBlockInputStream(const Block & block_) : block(block_) {} + explicit OneBlockInputStream(const Block & block_) : block(block_) {} String getName() const override { return "One"; } diff --git a/dbms/src/DataStreams/ParallelInputsProcessor.h b/dbms/src/DataStreams/ParallelInputsProcessor.h index 3f85238814a..505bfac567c 100644 --- a/dbms/src/DataStreams/ParallelInputsProcessor.h +++ b/dbms/src/DataStreams/ParallelInputsProcessor.h @@ -95,12 +95,11 @@ public: { active_threads = max_threads; threads.reserve(max_threads); - auto thread_group = CurrentThread::getGroup(); try { for (size_t i = 0; i < max_threads; ++i) - threads.emplace_back([=] () { thread(thread_group, i); }); + threads.emplace_back(&ParallelInputsProcessor::thread, this, CurrentThread::getGroup(), i); } catch (...) { diff --git a/dbms/src/DataStreams/PushingToViewsBlockOutputStream.cpp b/dbms/src/DataStreams/PushingToViewsBlockOutputStream.cpp index 195c5edcb07..304d7aa989c 100644 --- a/dbms/src/DataStreams/PushingToViewsBlockOutputStream.cpp +++ b/dbms/src/DataStreams/PushingToViewsBlockOutputStream.cpp @@ -63,6 +63,17 @@ PushingToViewsBlockOutputStream::PushingToViewsBlockOutputStream( } +Block PushingToViewsBlockOutputStream::getHeader() const +{ + /// If we don't write directly to the destination + /// then expect that we're inserting with precalculated virtual columns + if (output) + return storage->getSampleBlock(); + else + return storage->getSampleBlockWithVirtuals(); +} + + void PushingToViewsBlockOutputStream::write(const Block & block) { /** Throw an exception if the sizes of arrays - elements of nested data structures doesn't match. @@ -73,6 +84,8 @@ void PushingToViewsBlockOutputStream::write(const Block & block) Nested::validateArraySizes(block); if (output) + /// TODO: to support virtual and alias columns inside MVs, we should return here the inserted block extended + /// with additional columns directly from storage and pass it to MVs instead of raw block. output->write(block); /// Don't process materialized views if this block is duplicate diff --git a/dbms/src/DataStreams/PushingToViewsBlockOutputStream.h b/dbms/src/DataStreams/PushingToViewsBlockOutputStream.h index 3381a828ff0..34b8cb43042 100644 --- a/dbms/src/DataStreams/PushingToViewsBlockOutputStream.h +++ b/dbms/src/DataStreams/PushingToViewsBlockOutputStream.h @@ -22,7 +22,7 @@ public: const String & database, const String & table, const StoragePtr & storage_, const Context & context_, const ASTPtr & query_ptr_, bool no_destination = false); - Block getHeader() const override { return storage->getSampleBlock(); } + Block getHeader() const override; void write(const Block & block) override; void flush() override; diff --git a/dbms/src/DataStreams/TTLBlockInputStream.cpp b/dbms/src/DataStreams/TTLBlockInputStream.cpp index 482a3ff4814..1e765f8bb3c 100644 --- a/dbms/src/DataStreams/TTLBlockInputStream.cpp +++ b/dbms/src/DataStreams/TTLBlockInputStream.cpp @@ -26,6 +26,7 @@ TTLBlockInputStream::TTLBlockInputStream( , date_lut(DateLUT::instance()) { children.push_back(input_); + header = children.at(0)->getHeader(); const auto & column_defaults = storage.getColumns().getDefaults(); ASTPtr default_expr_list = std::make_shared(); @@ -58,11 +59,6 @@ TTLBlockInputStream::TTLBlockInputStream( } -Block TTLBlockInputStream::getHeader() const -{ - return children.at(0)->getHeader(); -} - Block TTLBlockInputStream::readImpl() { Block block = children.at(0)->read(); @@ -108,11 +104,13 @@ void TTLBlockInputStream::removeRowsWithExpiredTableTTL(Block & block) const auto & current = block.getByName(storage.ttl_table_entry.result_column); const IColumn * ttl_column = current.column.get(); + const auto & column_names = header.getNames(); MutableColumns result_columns; - result_columns.reserve(getHeader().columns()); - for (const auto & name : storage.getColumns().getNamesOfPhysical()) + result_columns.reserve(column_names.size()); + + for (auto it = column_names.begin(); it != column_names.end(); ++it) { - auto & column_with_type = block.getByName(name); + auto & column_with_type = block.getByName(*it); const IColumn * values_column = column_with_type.column.get(); MutableColumnPtr result_column = values_column->cloneEmpty(); result_column->reserve(block.rows()); @@ -125,13 +123,13 @@ void TTLBlockInputStream::removeRowsWithExpiredTableTTL(Block & block) new_ttl_infos.table_ttl.update(cur_ttl); result_column->insertFrom(*values_column, i); } - else + else if (it == column_names.begin()) ++rows_removed; } result_columns.emplace_back(std::move(result_column)); } - block = getHeader().cloneWithColumns(std::move(result_columns)); + block = header.cloneWithColumns(std::move(result_columns)); } void TTLBlockInputStream::removeValuesWithExpiredColumnTTL(Block & block) diff --git a/dbms/src/DataStreams/TTLBlockInputStream.h b/dbms/src/DataStreams/TTLBlockInputStream.h index a95cd627bc9..de0d4f9156b 100644 --- a/dbms/src/DataStreams/TTLBlockInputStream.h +++ b/dbms/src/DataStreams/TTLBlockInputStream.h @@ -21,7 +21,7 @@ public: String getName() const override { return "TTLBlockInputStream"; } - Block getHeader() const override; + Block getHeader() const override { return header; } protected: Block readImpl() override; @@ -47,6 +47,8 @@ private: std::unordered_map defaults_result_column; ExpressionActionsPtr defaults_expression; + + Block header; private: /// Removes values with expired ttl and computes new min_ttl and empty_columns for part void removeValuesWithExpiredColumnTTL(Block & block); diff --git a/dbms/src/DataStreams/processConstants.cpp b/dbms/src/DataStreams/processConstants.cpp index fff10afe780..6129c600bdf 100644 --- a/dbms/src/DataStreams/processConstants.cpp +++ b/dbms/src/DataStreams/processConstants.cpp @@ -9,7 +9,7 @@ void removeConstantsFromBlock(Block & block) size_t i = 0; while (i < columns) { - if (block.getByPosition(i).column->isColumnConst()) + if (block.getByPosition(i).column && isColumnConst(*block.getByPosition(i).column)) { block.erase(i); --columns; @@ -22,13 +22,14 @@ void removeConstantsFromBlock(Block & block) void removeConstantsFromSortDescription(const Block & header, SortDescription & description) { + /// Note: This code is not correct if column description contains column numbers instead of column names. + /// Hopefully, everywhere where it is used, column description contains names. description.erase(std::remove_if(description.begin(), description.end(), [&](const SortColumnDescription & elem) { - if (!elem.column_name.empty()) - return header.getByName(elem.column_name).column->isColumnConst(); - else - return header.safeGetByPosition(elem.column_number).column->isColumnConst(); + auto & column = !elem.column_name.empty() ? header.getByName(elem.column_name) + : header.safeGetByPosition(elem.column_number); + return column.column && isColumnConst(*column.column); }), description.end()); } @@ -41,7 +42,7 @@ void enrichBlockWithConstants(Block & block, const Block & header) for (size_t i = 0; i < columns; ++i) { const auto & col_type_name = header.getByPosition(i); - if (col_type_name.column->isColumnConst()) + if (col_type_name.column && isColumnConst(*col_type_name.column)) block.insert(i, {col_type_name.column->cloneResized(rows), col_type_name.type, col_type_name.name}); } } diff --git a/dbms/src/DataStreams/tests/collapsing_sorted_stream.cpp b/dbms/src/DataStreams/tests/collapsing_sorted_stream.cpp index a43b7d347eb..43205a9e7b5 100644 --- a/dbms/src/DataStreams/tests/collapsing_sorted_stream.cpp +++ b/dbms/src/DataStreams/tests/collapsing_sorted_stream.cpp @@ -68,6 +68,7 @@ try CollapsingFinalBlockInputStream collapsed(inputs, descr, "Sign"); Context context = Context::createGlobal(); + context.makeGlobalContext(); WriteBufferFromFileDescriptor out_buf(STDERR_FILENO); BlockOutputStreamPtr output = context.getOutputFormat("TabSeparated", out_buf, block1); diff --git a/dbms/src/DataStreams/tests/expression_stream.cpp b/dbms/src/DataStreams/tests/expression_stream.cpp index 3cbce14649d..b63d9d1f3b5 100644 --- a/dbms/src/DataStreams/tests/expression_stream.cpp +++ b/dbms/src/DataStreams/tests/expression_stream.cpp @@ -35,6 +35,7 @@ try ASTPtr ast = parseQuery(parser, input.data(), input.data() + input.size(), "", 0); Context context = Context::createGlobal(); + context.makeGlobalContext(); NamesAndTypesList source_columns = {{"number", std::make_shared()}}; auto syntax_result = SyntaxAnalyzer(context, {}).analyze(ast, source_columns); diff --git a/dbms/src/DataStreams/tests/filter_stream.cpp b/dbms/src/DataStreams/tests/filter_stream.cpp index ed12c09dc99..4199ba40b53 100644 --- a/dbms/src/DataStreams/tests/filter_stream.cpp +++ b/dbms/src/DataStreams/tests/filter_stream.cpp @@ -40,6 +40,7 @@ try std::cerr << std::endl; Context context = Context::createGlobal(); + context.makeGlobalContext(); NamesAndTypesList source_columns = {{"number", std::make_shared()}}; auto syntax_result = SyntaxAnalyzer(context, {}).analyze(ast, source_columns); diff --git a/dbms/src/DataStreams/tests/gtest_blocks_size_merging_streams.cpp b/dbms/src/DataStreams/tests/gtest_blocks_size_merging_streams.cpp index 9cbe82111a2..57cd68d16d8 100644 --- a/dbms/src/DataStreams/tests/gtest_blocks_size_merging_streams.cpp +++ b/dbms/src/DataStreams/tests/gtest_blocks_size_merging_streams.cpp @@ -1,9 +1,3 @@ -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" -#pragma clang diagnostic ignored "-Wundef" -#endif - #include #include #include diff --git a/dbms/src/DataStreams/tests/union_stream2.cpp b/dbms/src/DataStreams/tests/union_stream2.cpp index 284e66b91a9..3eb1927f80a 100644 --- a/dbms/src/DataStreams/tests/union_stream2.cpp +++ b/dbms/src/DataStreams/tests/union_stream2.cpp @@ -23,6 +23,7 @@ int main(int, char **) try { Context context = Context::createGlobal(); + context.makeGlobalContext(); Settings settings = context.getSettings(); context.setPath("./"); diff --git a/dbms/src/DataTypes/DataTypeAggregateFunction.cpp b/dbms/src/DataTypes/DataTypeAggregateFunction.cpp index a5dd5f8be62..a2c00e18acb 100644 --- a/dbms/src/DataTypes/DataTypeAggregateFunction.cpp +++ b/dbms/src/DataTypes/DataTypeAggregateFunction.cpp @@ -30,6 +30,7 @@ namespace ErrorCodes extern const int PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS; extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; extern const int LOGICAL_ERROR; + extern const int NOT_IMPLEMENTED; } @@ -216,6 +217,12 @@ void DataTypeAggregateFunction::deserializeTextQuoted(IColumn & column, ReadBuff } +void DataTypeAggregateFunction::deserializeWholeText(IColumn &, ReadBuffer &, const FormatSettings &) const +{ + throw Exception("AggregateFunction data type cannot be read from text", ErrorCodes::NOT_IMPLEMENTED); +} + + void DataTypeAggregateFunction::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { writeJSONString(serializeToString(function, column, row_num), ostr, settings); diff --git a/dbms/src/DataTypes/DataTypeAggregateFunction.h b/dbms/src/DataTypes/DataTypeAggregateFunction.h index 14407c8a90c..9ae7c67a803 100644 --- a/dbms/src/DataTypes/DataTypeAggregateFunction.h +++ b/dbms/src/DataTypes/DataTypeAggregateFunction.h @@ -52,6 +52,8 @@ public: void deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; void deserializeTextQuoted(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; + void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; void deserializeTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; diff --git a/dbms/src/DataTypes/DataTypeCustom.h b/dbms/src/DataTypes/DataTypeCustom.h index 0706803048d..c4f846d0259 100644 --- a/dbms/src/DataTypes/DataTypeCustom.h +++ b/dbms/src/DataTypes/DataTypeCustom.h @@ -33,6 +33,10 @@ public: */ virtual void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; + /** Text deserialization without quoting or escaping. + */ + virtual void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const = 0; + /** Text serialization with escaping but without quoting. */ virtual void serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; diff --git a/dbms/src/DataTypes/DataTypeCustomSimpleTextSerialization.cpp b/dbms/src/DataTypes/DataTypeCustomSimpleTextSerialization.cpp index 5f1e2ae5665..18b8798fe77 100644 --- a/dbms/src/DataTypes/DataTypeCustomSimpleTextSerialization.cpp +++ b/dbms/src/DataTypes/DataTypeCustomSimpleTextSerialization.cpp @@ -32,6 +32,13 @@ DataTypeCustomSimpleTextSerialization::~DataTypeCustomSimpleTextSerialization() { } +void DataTypeCustomSimpleTextSerialization::deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const +{ + String str; + readString(str, istr); + deserializeFromString(*this, column, str, settings); +} + void DataTypeCustomSimpleTextSerialization::serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { writeEscapedString(serializeToString(*this, column, row_num, settings), ostr); diff --git a/dbms/src/DataTypes/DataTypeCustomSimpleTextSerialization.h b/dbms/src/DataTypes/DataTypeCustomSimpleTextSerialization.h index ba483b4ff5c..e1c08d28738 100644 --- a/dbms/src/DataTypes/DataTypeCustomSimpleTextSerialization.h +++ b/dbms/src/DataTypes/DataTypeCustomSimpleTextSerialization.h @@ -21,6 +21,10 @@ public: virtual void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override = 0; virtual void deserializeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const = 0; + /** Text deserialization without quoting or escaping. + */ + void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; + /** Text serialization with escaping but without quoting. */ void serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; diff --git a/dbms/src/DataTypes/DataTypeDate.cpp b/dbms/src/DataTypes/DataTypeDate.cpp index 73edfd012fa..0b1f502b694 100644 --- a/dbms/src/DataTypes/DataTypeDate.cpp +++ b/dbms/src/DataTypes/DataTypeDate.cpp @@ -16,6 +16,11 @@ void DataTypeDate::serializeText(const IColumn & column, size_t row_num, WriteBu writeDateText(DayNum(static_cast(column).getData()[row_num]), ostr); } +void DataTypeDate::deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const +{ + deserializeTextEscaped(column, istr, settings); +} + void DataTypeDate::deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const { DayNum x; diff --git a/dbms/src/DataTypes/DataTypeDate.h b/dbms/src/DataTypes/DataTypeDate.h index a441d638cc4..7bd4c0d6b02 100644 --- a/dbms/src/DataTypes/DataTypeDate.h +++ b/dbms/src/DataTypes/DataTypeDate.h @@ -13,6 +13,7 @@ public: const char * getFamilyName() const override { return "Date"; } void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; + void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; void serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; void deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; diff --git a/dbms/src/DataTypes/DataTypeDateTime.cpp b/dbms/src/DataTypes/DataTypeDateTime.cpp index f3d6efa1488..a6b8f0da92a 100644 --- a/dbms/src/DataTypes/DataTypeDateTime.cpp +++ b/dbms/src/DataTypes/DataTypeDateTime.cpp @@ -62,6 +62,11 @@ static inline void readText(time_t & x, ReadBuffer & istr, const FormatSettings } +void DataTypeDateTime::deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const +{ + deserializeTextEscaped(column, istr, settings); +} + void DataTypeDateTime::deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const { time_t x; diff --git a/dbms/src/DataTypes/DataTypeDateTime.h b/dbms/src/DataTypes/DataTypeDateTime.h index 679a2777472..6a951e0e288 100644 --- a/dbms/src/DataTypes/DataTypeDateTime.h +++ b/dbms/src/DataTypes/DataTypeDateTime.h @@ -38,6 +38,7 @@ public: TypeIndex getTypeId() const override { return TypeIndex::DateTime; } void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; + void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override; void serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; void deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; diff --git a/dbms/src/DataTypes/DataTypeEnum.cpp b/dbms/src/DataTypes/DataTypeEnum.cpp index 24f760a1800..36a26540cda 100644 --- a/dbms/src/DataTypes/DataTypeEnum.cpp +++ b/dbms/src/DataTypes/DataTypeEnum.cpp @@ -166,6 +166,14 @@ void DataTypeEnum::deserializeTextQuoted(IColumn & column, ReadBuffer & is static_cast(column).getData().push_back(getValue(StringRef(field_name))); } +template +void DataTypeEnum::deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const +{ + std::string field_name; + readString(field_name, istr); + static_cast(column).getData().push_back(getValue(StringRef(field_name))); +} + template void DataTypeEnum::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { @@ -342,9 +350,20 @@ Field DataTypeEnum::castToValue(const Field & value_or_name) const template class DataTypeEnum; template class DataTypeEnum; +static void checkASTStructure(const ASTPtr & child) +{ + const auto * func = child->as(); + if (!func + || func->name != "equals" + || func->parameters + || !func->arguments + || func->arguments->children.size() != 2) + throw Exception("Elements of Enum data type must be of form: 'name' = number, where name is string literal and number is an integer", + ErrorCodes::UNEXPECTED_AST_STRUCTURE); +} template -static DataTypePtr create(const ASTPtr & arguments) +static DataTypePtr createExact(const ASTPtr & arguments) { if (!arguments || arguments->children.empty()) throw Exception("Enum data type cannot be empty", ErrorCodes::EMPTY_DATA_PASSED); @@ -357,15 +376,9 @@ static DataTypePtr create(const ASTPtr & arguments) /// Children must be functions 'equals' with string literal as left argument and numeric literal as right argument. for (const ASTPtr & child : arguments->children) { - const auto * func = child->as(); - if (!func - || func->name != "equals" - || func->parameters - || !func->arguments - || func->arguments->children.size() != 2) - throw Exception("Elements of Enum data type must be of form: 'name' = number, where name is string literal and number is an integer", - ErrorCodes::UNEXPECTED_AST_STRUCTURE); + checkASTStructure(child); + const auto * func = child->as(); const auto * name_literal = func->arguments->children[0]->as(); const auto * value_literal = func->arguments->children[1]->as(); @@ -389,11 +402,38 @@ static DataTypePtr create(const ASTPtr & arguments) return std::make_shared(values); } +static DataTypePtr create(const ASTPtr & arguments) +{ + if (!arguments || arguments->children.empty()) + throw Exception("Enum data type cannot be empty", ErrorCodes::EMPTY_DATA_PASSED); + + /// Children must be functions 'equals' with string literal as left argument and numeric literal as right argument. + for (const ASTPtr & child : arguments->children) + { + checkASTStructure(child); + + const auto * func = child->as(); + const auto * value_literal = func->arguments->children[1]->as(); + + if (!value_literal + || (value_literal->value.getType() != Field::Types::UInt64 && value_literal->value.getType() != Field::Types::Int64)) + throw Exception("Elements of Enum data type must be of form: 'name' = number, where name is string literal and number is an integer", + ErrorCodes::UNEXPECTED_AST_STRUCTURE); + + Int64 value = value_literal->value.get(); + + if (value > std::numeric_limits::max() || value < std::numeric_limits::min()) + return createExact(arguments); + } + + return createExact(arguments); +} void registerDataTypeEnum(DataTypeFactory & factory) { - factory.registerDataType("Enum8", create>); - factory.registerDataType("Enum16", create>); + factory.registerDataType("Enum8", createExact>); + factory.registerDataType("Enum16", createExact>); + factory.registerDataType("Enum", create); } } diff --git a/dbms/src/DataTypes/DataTypeEnum.h b/dbms/src/DataTypes/DataTypeEnum.h index 19d4ad691dc..b99e2383860 100644 --- a/dbms/src/DataTypes/DataTypeEnum.h +++ b/dbms/src/DataTypes/DataTypeEnum.h @@ -96,6 +96,8 @@ public: void deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; void deserializeTextQuoted(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; + void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; void deserializeTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; diff --git a/dbms/src/DataTypes/DataTypeFixedString.cpp b/dbms/src/DataTypes/DataTypeFixedString.cpp index d1a007e16d2..34970fdaae9 100644 --- a/dbms/src/DataTypes/DataTypeFixedString.cpp +++ b/dbms/src/DataTypes/DataTypeFixedString.cpp @@ -176,6 +176,12 @@ void DataTypeFixedString::deserializeTextQuoted(IColumn & column, ReadBuffer & i } +void DataTypeFixedString::deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const +{ + read(*this, column, [&istr](ColumnFixedString::Chars & data) { readStringInto(data, istr); }); +} + + void DataTypeFixedString::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { const char * pos = reinterpret_cast(&static_cast(column).getChars()[n * row_num]); diff --git a/dbms/src/DataTypes/DataTypeFixedString.h b/dbms/src/DataTypes/DataTypeFixedString.h index 3019b6d225d..1a8a33d95c6 100644 --- a/dbms/src/DataTypes/DataTypeFixedString.h +++ b/dbms/src/DataTypes/DataTypeFixedString.h @@ -50,6 +50,8 @@ public: void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; + void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; + void serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; void deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; diff --git a/dbms/src/DataTypes/DataTypeLowCardinality.cpp b/dbms/src/DataTypes/DataTypeLowCardinality.cpp index e70223437f7..33d3eb658d3 100644 --- a/dbms/src/DataTypes/DataTypeLowCardinality.cpp +++ b/dbms/src/DataTypes/DataTypeLowCardinality.cpp @@ -544,7 +544,7 @@ void DataTypeLowCardinality::serializeBinaryBulkWithMultipleStreams( ErrorCodes::LOGICAL_ERROR); } - if (auto nullable_keys = typeid_cast(keys.get())) + if (auto * nullable_keys = checkAndGetColumn(*keys)) keys = nullable_keys->getNestedColumnPtr(); bool need_additional_keys = !keys->empty(); diff --git a/dbms/src/DataTypes/DataTypeLowCardinality.h b/dbms/src/DataTypes/DataTypeLowCardinality.h index 1742c1cb2e9..8e6e12fadba 100644 --- a/dbms/src/DataTypes/DataTypeLowCardinality.h +++ b/dbms/src/DataTypes/DataTypeLowCardinality.h @@ -81,6 +81,11 @@ public: deserializeImpl(column, &IDataType::deserializeAsTextQuoted, istr, settings); } + void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override + { + deserializeImpl(column, &IDataType::deserializeAsTextEscaped, istr, settings); + } + void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const override { serializeImpl(column, row_num, &IDataType::serializeAsTextCSV, ostr, settings); diff --git a/dbms/src/DataTypes/DataTypeNullable.cpp b/dbms/src/DataTypes/DataTypeNullable.cpp index 0bfe8a157d6..c56d8616be2 100644 --- a/dbms/src/DataTypes/DataTypeNullable.cpp +++ b/dbms/src/DataTypes/DataTypeNullable.cpp @@ -251,6 +251,15 @@ void DataTypeNullable::deserializeTextQuoted(IColumn & column, ReadBuffer & istr [this, &istr, &settings] (IColumn & nested) { nested_data_type->deserializeAsTextQuoted(nested, istr, settings); }); } + +void DataTypeNullable::deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const +{ + safeDeserialize(column, + [&istr] { return checkStringByFirstCharacterAndAssertTheRestCaseInsensitive("NULL", istr); }, + [this, &istr, &settings] (IColumn & nested) { nested_data_type->deserializeAsWholeText(nested, istr, settings); }); +} + + void DataTypeNullable::serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { const ColumnNullable & col = static_cast(column); diff --git a/dbms/src/DataTypes/DataTypeNullable.h b/dbms/src/DataTypes/DataTypeNullable.h index 1081f84dd11..2b098ea0476 100644 --- a/dbms/src/DataTypes/DataTypeNullable.h +++ b/dbms/src/DataTypes/DataTypeNullable.h @@ -53,6 +53,7 @@ public: void deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; void deserializeTextQuoted(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; + void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; diff --git a/dbms/src/DataTypes/DataTypeString.cpp b/dbms/src/DataTypes/DataTypeString.cpp index d3334ef93bf..5d104c76fef 100644 --- a/dbms/src/DataTypes/DataTypeString.cpp +++ b/dbms/src/DataTypes/DataTypeString.cpp @@ -244,6 +244,12 @@ static inline void read(IColumn & column, Reader && reader) } +void DataTypeString::deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const +{ + read(column, [&](ColumnString::Chars & data) { readStringInto(data, istr); }); +} + + void DataTypeString::deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const { read(column, [&](ColumnString::Chars & data) { readEscapedStringInto(data, istr); }); diff --git a/dbms/src/DataTypes/DataTypeString.h b/dbms/src/DataTypes/DataTypeString.h index 0a3d2277e79..3cf85f69a1f 100644 --- a/dbms/src/DataTypes/DataTypeString.h +++ b/dbms/src/DataTypes/DataTypeString.h @@ -30,6 +30,7 @@ public: void deserializeBinaryBulk(IColumn & column, ReadBuffer & istr, size_t limit, double avg_value_size_hint) const override; void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; + void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; void serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; void deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; diff --git a/dbms/src/DataTypes/DataTypeWithSimpleSerialization.h b/dbms/src/DataTypes/DataTypeWithSimpleSerialization.h index 8f897153fd0..6f6120deb4f 100644 --- a/dbms/src/DataTypes/DataTypeWithSimpleSerialization.h +++ b/dbms/src/DataTypes/DataTypeWithSimpleSerialization.h @@ -32,6 +32,11 @@ protected: serializeText(column, row_num, ostr, settings); } + void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override + { + deserializeText(column, istr, settings); + } + void deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const override { deserializeText(column, istr, settings); diff --git a/dbms/src/DataTypes/DataTypesDecimal.cpp b/dbms/src/DataTypes/DataTypesDecimal.cpp index 9dd811e7aec..920d7b360bd 100644 --- a/dbms/src/DataTypes/DataTypesDecimal.cpp +++ b/dbms/src/DataTypes/DataTypesDecimal.cpp @@ -241,7 +241,7 @@ static DataTypePtr create(const ASTPtr & arguments) } template -static DataTypePtr createExect(const ASTPtr & arguments) +static DataTypePtr createExact(const ASTPtr & arguments) { if (!arguments || arguments->children.size() != 1) throw Exception("Decimal data type family must have exactly two arguments: precision and scale", @@ -260,9 +260,9 @@ static DataTypePtr createExect(const ASTPtr & arguments) void registerDataTypeDecimal(DataTypeFactory & factory) { - factory.registerDataType("Decimal32", createExect, DataTypeFactory::CaseInsensitive); - factory.registerDataType("Decimal64", createExect, DataTypeFactory::CaseInsensitive); - factory.registerDataType("Decimal128", createExect, DataTypeFactory::CaseInsensitive); + factory.registerDataType("Decimal32", createExact, DataTypeFactory::CaseInsensitive); + factory.registerDataType("Decimal64", createExact, DataTypeFactory::CaseInsensitive); + factory.registerDataType("Decimal128", createExact, DataTypeFactory::CaseInsensitive); factory.registerDataType("Decimal", create, DataTypeFactory::CaseInsensitive); factory.registerAlias("DEC", "Decimal", DataTypeFactory::CaseInsensitive); diff --git a/dbms/src/DataTypes/IDataType.cpp b/dbms/src/DataTypes/IDataType.cpp index 09c080f56cc..39d269d8613 100644 --- a/dbms/src/DataTypes/IDataType.cpp +++ b/dbms/src/DataTypes/IDataType.cpp @@ -142,121 +142,89 @@ void IDataType::insertDefaultInto(IColumn & column) const void IDataType::serializeAsTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { if (custom_text_serialization) - { custom_text_serialization->serializeTextEscaped(column, row_num, ostr, settings); - } else - { serializeTextEscaped(column, row_num, ostr, settings); - } } void IDataType::deserializeAsTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const { if (custom_text_serialization) - { custom_text_serialization->deserializeTextEscaped(column, istr, settings); - } else - { deserializeTextEscaped(column, istr, settings); - } } void IDataType::serializeAsTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { if (custom_text_serialization) - { custom_text_serialization->serializeTextQuoted(column, row_num, ostr, settings); - } else - { serializeTextQuoted(column, row_num, ostr, settings); - } } void IDataType::deserializeAsTextQuoted(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const { if (custom_text_serialization) - { custom_text_serialization->deserializeTextQuoted(column, istr, settings); - } else - { deserializeTextQuoted(column, istr, settings); - } } void IDataType::serializeAsTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { if (custom_text_serialization) - { custom_text_serialization->serializeTextCSV(column, row_num, ostr, settings); - } else - { serializeTextCSV(column, row_num, ostr, settings); - } } void IDataType::deserializeAsTextCSV(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const { if (custom_text_serialization) - { custom_text_serialization->deserializeTextCSV(column, istr, settings); - } else - { deserializeTextCSV(column, istr, settings); - } } void IDataType::serializeAsText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { if (custom_text_serialization) - { custom_text_serialization->serializeText(column, row_num, ostr, settings); - } else - { serializeText(column, row_num, ostr, settings); - } +} + +void IDataType::deserializeAsWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const +{ + if (custom_text_serialization) + custom_text_serialization->deserializeWholeText(column, istr, settings); + else + deserializeWholeText(column, istr, settings); } void IDataType::serializeAsTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { if (custom_text_serialization) - { custom_text_serialization->serializeTextJSON(column, row_num, ostr, settings); - } else - { serializeTextJSON(column, row_num, ostr, settings); - } } void IDataType::deserializeAsTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings & settings) const { if (custom_text_serialization) - { custom_text_serialization->deserializeTextJSON(column, istr, settings); - } else - { deserializeTextJSON(column, istr, settings); - } } void IDataType::serializeAsTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { if (custom_text_serialization) - { custom_text_serialization->serializeTextXML(column, row_num, ostr, settings); - } else - { serializeTextXML(column, row_num, ostr, settings); - } } void IDataType::setCustomization(DataTypeCustomDescPtr custom_desc_) const diff --git a/dbms/src/DataTypes/IDataType.h b/dbms/src/DataTypes/IDataType.h index 1a6c87b64ce..f4c22ff9ac8 100644 --- a/dbms/src/DataTypes/IDataType.h +++ b/dbms/src/DataTypes/IDataType.h @@ -222,76 +222,60 @@ public: /// If method will throw an exception, then column will be in same state as before call to method. virtual void deserializeBinary(IColumn & column, ReadBuffer & istr) const = 0; - /** Text serialization with escaping but without quoting. - */ - virtual void serializeAsTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const; - - virtual void deserializeAsTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const; - - /** Text serialization as a literal that may be inserted into a query. - */ - virtual void serializeAsTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const; - - virtual void deserializeAsTextQuoted(IColumn & column, ReadBuffer & istr, const FormatSettings &) const; - - /** Text serialization for the CSV format. - */ - virtual void serializeAsTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const; - virtual void deserializeAsTextCSV(IColumn & column, ReadBuffer & istr, const FormatSettings &) const; - - /** Text serialization for displaying on a terminal or saving into a text file, and the like. - * Without escaping or quoting. - */ - virtual void serializeAsText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const; - - /** Text serialization intended for using in JSON format. - */ - virtual void serializeAsTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const; - virtual void deserializeAsTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings &) const; - - /** Text serialization for putting into the XML format. - */ - virtual void serializeAsTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const; - /** Serialize to a protobuf. */ virtual void serializeProtobuf(const IColumn & column, size_t row_num, ProtobufWriter & protobuf, size_t & value_index) const = 0; virtual void deserializeProtobuf(IColumn & column, ProtobufReader & protobuf, bool allow_add_row, bool & row_added) const = 0; -protected: - virtual String doGetName() const; - /** Text serialization with escaping but without quoting. */ -public: // used somewhere in arcadia - virtual void serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; + void serializeAsTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const; -protected: - virtual void deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const = 0; + void deserializeAsTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const; /** Text serialization as a literal that may be inserted into a query. */ - virtual void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; + void serializeAsTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const; - virtual void deserializeTextQuoted(IColumn & column, ReadBuffer & istr, const FormatSettings &) const = 0; + void deserializeAsTextQuoted(IColumn & column, ReadBuffer & istr, const FormatSettings &) const; /** Text serialization for the CSV format. */ - virtual void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; - virtual void deserializeTextCSV(IColumn & column, ReadBuffer & istr, const FormatSettings &) const = 0; + void serializeAsTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const; + void deserializeAsTextCSV(IColumn & column, ReadBuffer & istr, const FormatSettings &) const; /** Text serialization for displaying on a terminal or saving into a text file, and the like. * Without escaping or quoting. */ - virtual void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; + void serializeAsText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const; + + /** Text deserialization in case when buffer contains only one value, without any escaping and delimiters. + */ + void deserializeAsWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const; /** Text serialization intended for using in JSON format. - * force_quoting_64bit_integers parameter forces to brace UInt64 and Int64 types into quotes. */ - virtual void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; - virtual void deserializeTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings &) const = 0; + void serializeAsTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const; + void deserializeAsTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings &) const; /** Text serialization for putting into the XML format. */ + void serializeAsTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const; + +protected: + virtual String doGetName() const; + + /// Default implementations of text serialization in case of 'custom_text_serialization' is not set. + + virtual void serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; + virtual void deserializeTextEscaped(IColumn & column, ReadBuffer & istr, const FormatSettings &) const = 0; + virtual void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; + virtual void deserializeTextQuoted(IColumn & column, ReadBuffer & istr, const FormatSettings &) const = 0; + virtual void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; + virtual void deserializeTextCSV(IColumn & column, ReadBuffer & istr, const FormatSettings &) const = 0; + virtual void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; + virtual void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const = 0; + virtual void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const = 0; + virtual void deserializeTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings &) const = 0; virtual void serializeTextXML(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const { serializeText(column, row_num, ostr, settings); @@ -471,7 +455,6 @@ private: public: const IDataTypeCustomName * getCustomName() const { return custom_name.get(); } - const IDataTypeCustomTextSerialization * getCustomTextSerialization() const { return custom_text_serialization.get(); } }; diff --git a/dbms/src/DataTypes/NestedUtils.cpp b/dbms/src/DataTypes/NestedUtils.cpp index ce421079bbf..b3399ddfc1c 100644 --- a/dbms/src/DataTypes/NestedUtils.cpp +++ b/dbms/src/DataTypes/NestedUtils.cpp @@ -91,7 +91,7 @@ Block flatten(const Block & block) const Strings & names = type_tuple->getElementNames(); size_t tuple_size = element_types.size(); - bool is_const = elem.column->isColumnConst(); + bool is_const = isColumnConst(*elem.column); const ColumnArray * column_array; if (is_const) column_array = typeid_cast(&static_cast(*elem.column).getDataColumn()); diff --git a/dbms/src/DataTypes/tests/gtest_data_type_get_common_type.cpp b/dbms/src/DataTypes/tests/gtest_data_type_get_common_type.cpp index d2782ae9179..8ad8e955e75 100644 --- a/dbms/src/DataTypes/tests/gtest_data_type_get_common_type.cpp +++ b/dbms/src/DataTypes/tests/gtest_data_type_get_common_type.cpp @@ -4,11 +4,6 @@ #include -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ - #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" - #pragma clang diagnostic ignored "-Wundef" -#endif #include diff --git a/dbms/src/Databases/DatabaseDictionary.cpp b/dbms/src/Databases/DatabaseDictionary.cpp index 01aa397148f..4451b320e44 100644 --- a/dbms/src/Databases/DatabaseDictionary.cpp +++ b/dbms/src/Databases/DatabaseDictionary.cpp @@ -52,7 +52,7 @@ Tables DatabaseDictionary::listTables(const Context & context, const FilterByNam auto dict_name = dict_ptr->getName(); const DictionaryStructure & dictionary_structure = dict_ptr->getStructure(); auto columns = StorageDictionary::getNamesAndTypes(dictionary_structure); - tables[dict_name] = StorageDictionary::create(dict_name, ColumnsDescription{columns}, context, true, dict_name); + tables[dict_name] = StorageDictionary::create(getDatabaseName(), dict_name, ColumnsDescription{columns}, context, true, dict_name); } return tables; } @@ -73,7 +73,7 @@ StoragePtr DatabaseDictionary::tryGetTable( { const DictionaryStructure & dictionary_structure = dict_ptr->getStructure(); auto columns = StorageDictionary::getNamesAndTypes(dictionary_structure); - return StorageDictionary::create(table_name, ColumnsDescription{columns}, context, true, table_name); + return StorageDictionary::create(getDatabaseName(), table_name, ColumnsDescription{columns}, context, true, table_name); } return {}; @@ -86,7 +86,7 @@ DatabaseIteratorPtr DatabaseDictionary::getIterator(const Context & context, con bool DatabaseDictionary::empty(const Context & context) const { - return context.getExternalDictionaries().getNumberOfNames() == 0; + return !context.getExternalDictionaries().hasCurrentlyLoadedObjects(); } StoragePtr DatabaseDictionary::detachTable(const String & /*table_name*/) diff --git a/dbms/src/Databases/DatabaseMySQL.cpp b/dbms/src/Databases/DatabaseMySQL.cpp index af8b129d3b0..e9dd5c0dacc 100644 --- a/dbms/src/Databases/DatabaseMySQL.cpp +++ b/dbms/src/Databases/DatabaseMySQL.cpp @@ -230,7 +230,7 @@ DatabaseMySQL::MySQLStorageInfo DatabaseMySQL::createStorageInfo( const String & table_name, const NamesAndTypesList & columns_name_and_type, const UInt64 & table_modification_time) const { const auto & mysql_table = StorageMySQL::create( - table_name, std::move(mysql_pool), mysql_database_name, table_name, + database_name, table_name, std::move(mysql_pool), mysql_database_name, table_name, false, "", ColumnsDescription{columns_name_and_type}, global_context); const auto & create_table_query = std::make_shared(); diff --git a/dbms/src/Dictionaries/ClickHouseDictionarySource.cpp b/dbms/src/Dictionaries/ClickHouseDictionarySource.cpp index 3703d11d832..cd977d18ad0 100644 --- a/dbms/src/Dictionaries/ClickHouseDictionarySource.cpp +++ b/dbms/src/Dictionaries/ClickHouseDictionarySource.cpp @@ -74,6 +74,8 @@ ClickHouseDictionarySource::ClickHouseDictionarySource( { /// We should set user info even for the case when the dictionary is loaded in-process (without TCP communication). context.setUser(user, password, Poco::Net::SocketAddress("127.0.0.1", 0), {}); + /// Processors are not supported here yet. + context.getSettingsRef().experimental_use_processors = false; } diff --git a/dbms/src/Dictionaries/ClickHouseDictionarySource.h b/dbms/src/Dictionaries/ClickHouseDictionarySource.h index 2603f24fa0f..991782b1549 100644 --- a/dbms/src/Dictionaries/ClickHouseDictionarySource.h +++ b/dbms/src/Dictionaries/ClickHouseDictionarySource.h @@ -27,6 +27,7 @@ public: /// copy-constructor is provided in order to support cloneability ClickHouseDictionarySource(const ClickHouseDictionarySource & other); + ClickHouseDictionarySource & operator=(const ClickHouseDictionarySource &) = delete; BlockInputStreamPtr loadAll() override; diff --git a/dbms/src/Dictionaries/ExecutableDictionarySource.h b/dbms/src/Dictionaries/ExecutableDictionarySource.h index c5ace9ab78f..9816161a70e 100644 --- a/dbms/src/Dictionaries/ExecutableDictionarySource.h +++ b/dbms/src/Dictionaries/ExecutableDictionarySource.h @@ -23,6 +23,7 @@ public: const Context & context); ExecutableDictionarySource(const ExecutableDictionarySource & other); + ExecutableDictionarySource & operator=(const ExecutableDictionarySource &) = delete; BlockInputStreamPtr loadAll() override; diff --git a/dbms/src/Dictionaries/HTTPDictionarySource.h b/dbms/src/Dictionaries/HTTPDictionarySource.h index 92980e183e3..78fe5193533 100644 --- a/dbms/src/Dictionaries/HTTPDictionarySource.h +++ b/dbms/src/Dictionaries/HTTPDictionarySource.h @@ -26,6 +26,7 @@ public: const Context & context); HTTPDictionarySource(const HTTPDictionarySource & other); + HTTPDictionarySource & operator=(const HTTPDictionarySource &) = delete; BlockInputStreamPtr loadAll() override; diff --git a/dbms/src/Dictionaries/LibraryDictionarySource.h b/dbms/src/Dictionaries/LibraryDictionarySource.h index a667b286be3..d09e5eee691 100644 --- a/dbms/src/Dictionaries/LibraryDictionarySource.h +++ b/dbms/src/Dictionaries/LibraryDictionarySource.h @@ -35,6 +35,7 @@ public: Block & sample_block); LibraryDictionarySource(const LibraryDictionarySource & other); + LibraryDictionarySource & operator=(const LibraryDictionarySource &) = delete; ~LibraryDictionarySource() override; diff --git a/dbms/src/Dictionaries/MySQLDictionarySource.h b/dbms/src/Dictionaries/MySQLDictionarySource.h index 30447a49aea..cfc45f42bb3 100644 --- a/dbms/src/Dictionaries/MySQLDictionarySource.h +++ b/dbms/src/Dictionaries/MySQLDictionarySource.h @@ -37,6 +37,7 @@ public: /// copy-constructor is provided in order to support cloneability MySQLDictionarySource(const MySQLDictionarySource & other); + MySQLDictionarySource & operator=(const MySQLDictionarySource &) = delete; BlockInputStreamPtr loadAll() override; diff --git a/dbms/src/Dictionaries/XDBCDictionarySource.h b/dbms/src/Dictionaries/XDBCDictionarySource.h index 5197300c341..253f802d8fd 100644 --- a/dbms/src/Dictionaries/XDBCDictionarySource.h +++ b/dbms/src/Dictionaries/XDBCDictionarySource.h @@ -36,6 +36,7 @@ public: /// copy-constructor is provided in order to support cloneability XDBCDictionarySource(const XDBCDictionarySource & other); + XDBCDictionarySource & operator=(const XDBCDictionarySource &) = delete; BlockInputStreamPtr loadAll() override; diff --git a/dbms/src/Formats/BinaryRowInputStream.cpp b/dbms/src/Formats/BinaryRowInputStream.cpp index c710b17ee9e..9177a70bb18 100644 --- a/dbms/src/Formats/BinaryRowInputStream.cpp +++ b/dbms/src/Formats/BinaryRowInputStream.cpp @@ -65,11 +65,12 @@ void registerInputFormatRowBinary(FormatFactory & factory) const Context &, UInt64 max_block_size, UInt64 rows_portion_size, + FormatFactory::ReadCallback callback, const FormatSettings & settings) { return std::make_shared( std::make_shared(buf, sample, false, false), - sample, max_block_size, rows_portion_size, settings); + sample, max_block_size, rows_portion_size, callback, settings); }); factory.registerInputFormat("RowBinaryWithNamesAndTypes", []( @@ -78,11 +79,12 @@ void registerInputFormatRowBinary(FormatFactory & factory) const Context &, UInt64 max_block_size, UInt64 rows_portion_size, + FormatFactory::ReadCallback callback, const FormatSettings & settings) { return std::make_shared( std::make_shared(buf, sample, true, true), - sample, max_block_size, rows_portion_size, settings); + sample, max_block_size, rows_portion_size, callback, settings); }); } diff --git a/dbms/src/Formats/BlockInputStreamFromRowInputStream.cpp b/dbms/src/Formats/BlockInputStreamFromRowInputStream.cpp index b67ce9b28cd..2335363db70 100644 --- a/dbms/src/Formats/BlockInputStreamFromRowInputStream.cpp +++ b/dbms/src/Formats/BlockInputStreamFromRowInputStream.cpp @@ -28,9 +28,15 @@ BlockInputStreamFromRowInputStream::BlockInputStreamFromRowInputStream( const Block & sample_, UInt64 max_block_size_, UInt64 rows_portion_size_, + FormatFactory::ReadCallback callback, const FormatSettings & settings) - : row_input(row_input_), sample(sample_), max_block_size(max_block_size_), rows_portion_size(rows_portion_size_), - allow_errors_num(settings.input_allow_errors_num), allow_errors_ratio(settings.input_allow_errors_ratio) + : row_input(row_input_) + , sample(sample_) + , max_block_size(max_block_size_) + , rows_portion_size(rows_portion_size_) + , read_virtual_columns_callback(callback) + , allow_errors_num(settings.input_allow_errors_num) + , allow_errors_ratio(settings.input_allow_errors_ratio) { } @@ -73,6 +79,8 @@ Block BlockInputStreamFromRowInputStream::readImpl() RowReadExtension info; if (!row_input->read(columns, info)) break; + if (read_virtual_columns_callback) + read_virtual_columns_callback(); for (size_t column_idx = 0; column_idx < info.read_columns.size(); ++column_idx) { diff --git a/dbms/src/Formats/BlockInputStreamFromRowInputStream.h b/dbms/src/Formats/BlockInputStreamFromRowInputStream.h index 2f91aa2ecb2..2338af3bf38 100644 --- a/dbms/src/Formats/BlockInputStreamFromRowInputStream.h +++ b/dbms/src/Formats/BlockInputStreamFromRowInputStream.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -24,6 +25,7 @@ public: const Block & sample_, UInt64 max_block_size_, UInt64 rows_portion_size_, + FormatFactory::ReadCallback callback, const FormatSettings & settings); void readPrefix() override { row_input->readPrefix(); } @@ -45,6 +47,10 @@ private: Block sample; UInt64 max_block_size; UInt64 rows_portion_size; + + /// Callback used to setup virtual columns after reading each row. + FormatFactory::ReadCallback read_virtual_columns_callback; + BlockMissingValues block_missing_values; UInt64 allow_errors_num; diff --git a/dbms/src/Formats/CSVRowInputStream.cpp b/dbms/src/Formats/CSVRowInputStream.cpp index 9108c7df3d1..07cfd4826df 100644 --- a/dbms/src/Formats/CSVRowInputStream.cpp +++ b/dbms/src/Formats/CSVRowInputStream.cpp @@ -531,11 +531,12 @@ void registerInputFormatCSV(FormatFactory & factory) const Context &, UInt64 max_block_size, UInt64 rows_portion_size, + FormatFactory::ReadCallback callback, const FormatSettings & settings) { return std::make_shared( std::make_shared(buf, sample, with_names, settings), - sample, max_block_size, rows_portion_size, settings); + sample, max_block_size, rows_portion_size, callback, settings); }); } } diff --git a/dbms/src/Formats/CapnProtoRowInputStream.cpp b/dbms/src/Formats/CapnProtoRowInputStream.cpp index 5424e233618..96c3c5fded3 100644 --- a/dbms/src/Formats/CapnProtoRowInputStream.cpp +++ b/dbms/src/Formats/CapnProtoRowInputStream.cpp @@ -308,6 +308,7 @@ void registerInputFormatCapnProto(FormatFactory & factory) const Context & context, UInt64 max_block_size, UInt64 rows_portion_size, + FormatFactory::ReadCallback callback, const FormatSettings & settings) { return std::make_shared( @@ -315,6 +316,7 @@ void registerInputFormatCapnProto(FormatFactory & factory) sample, max_block_size, rows_portion_size, + callback, settings); }); } diff --git a/dbms/src/Formats/FormatFactory.cpp b/dbms/src/Formats/FormatFactory.cpp index d1b3bac5e3d..4fae140abee 100644 --- a/dbms/src/Formats/FormatFactory.cpp +++ b/dbms/src/Formats/FormatFactory.cpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace DB @@ -26,15 +27,16 @@ const FormatFactory::Creators & FormatFactory::getCreators(const String & name) throw Exception("Unknown format " + name, ErrorCodes::UNKNOWN_FORMAT); } - -BlockInputStreamPtr FormatFactory::getInput(const String & name, ReadBuffer & buf, const Block & sample, const Context & context, UInt64 max_block_size, UInt64 rows_portion_size) const +const FormatFactory::ProcessorCreators & FormatFactory::getProcessorCreators(const String & name) const { - const auto & input_getter = getCreators(name).first; - if (!input_getter) - throw Exception("Format " + name + " is not suitable for input", ErrorCodes::FORMAT_IS_NOT_SUITABLE_FOR_INPUT); - - const Settings & settings = context.getSettingsRef(); + auto it = processors_dict.find(name); + if (processors_dict.end() != it) + return it->second; + throw Exception("Unknown format " + name, ErrorCodes::UNKNOWN_FORMAT); +} +static FormatSettings getInputFormatSetting(const Settings & settings) +{ FormatSettings format_settings; format_settings.csv.delimiter = settings.format_csv_delimiter; format_settings.csv.allow_single_quotes = settings.format_csv_allow_single_quotes; @@ -48,18 +50,11 @@ BlockInputStreamPtr FormatFactory::getInput(const String & name, ReadBuffer & bu format_settings.input_allow_errors_num = settings.input_format_allow_errors_num; format_settings.input_allow_errors_ratio = settings.input_format_allow_errors_ratio; - return input_getter(buf, sample, context, max_block_size, rows_portion_size, format_settings); + return format_settings; } - -BlockOutputStreamPtr FormatFactory::getOutput(const String & name, WriteBuffer & buf, const Block & sample, const Context & context) const +static FormatSettings getOutputFormatSetting(const Settings & settings) { - const auto & output_getter = getCreators(name).second; - if (!output_getter) - throw Exception("Format " + name + " is not suitable for output", ErrorCodes::FORMAT_IS_NOT_SUITABLE_FOR_OUTPUT); - - const Settings & settings = context.getSettingsRef(); - FormatSettings format_settings; format_settings.json.quote_64bit_integers = settings.output_format_json_quote_64bit_integers; format_settings.json.quote_denormals = settings.output_format_json_quote_denormals; @@ -73,6 +68,40 @@ BlockOutputStreamPtr FormatFactory::getOutput(const String & name, WriteBuffer & format_settings.write_statistics = settings.output_format_write_statistics; format_settings.parquet.row_group_size = settings.output_format_parquet_row_group_size; + return format_settings; +} + + +BlockInputStreamPtr FormatFactory::getInput( + const String & name, + ReadBuffer & buf, + const Block & sample, + const Context & context, + UInt64 max_block_size, + UInt64 rows_portion_size, + ReadCallback callback) const +{ + const auto & input_getter = getCreators(name).first; + if (!input_getter) + throw Exception("Format " + name + " is not suitable for input", ErrorCodes::FORMAT_IS_NOT_SUITABLE_FOR_INPUT); + + const Settings & settings = context.getSettingsRef(); + FormatSettings format_settings = getInputFormatSetting(settings); + + return input_getter( + buf, sample, context, max_block_size, rows_portion_size, callback ? callback : ReadCallback(), format_settings); +} + + +BlockOutputStreamPtr FormatFactory::getOutput(const String & name, WriteBuffer & buf, const Block & sample, const Context & context) const +{ + const auto & output_getter = getCreators(name).second; + if (!output_getter) + throw Exception("Format " + name + " is not suitable for output", ErrorCodes::FORMAT_IS_NOT_SUITABLE_FOR_OUTPUT); + + const Settings & settings = context.getSettingsRef(); + FormatSettings format_settings = getOutputFormatSetting(settings); + /** Materialization is needed, because formats can use the functions `IDataType`, * which only work with full columns. */ @@ -81,12 +110,46 @@ BlockOutputStreamPtr FormatFactory::getOutput(const String & name, WriteBuffer & } +InputFormatPtr FormatFactory::getInputFormat(const String & name, ReadBuffer & buf, const Block & sample, const Context & context, UInt64 max_block_size) const +{ + const auto & input_getter = getProcessorCreators(name).first; + if (!input_getter) + throw Exception("Format " + name + " is not suitable for input", ErrorCodes::FORMAT_IS_NOT_SUITABLE_FOR_INPUT); + + const Settings & settings = context.getSettingsRef(); + FormatSettings format_settings = getInputFormatSetting(settings); + + RowInputFormatParams params; + params.max_block_size = max_block_size; + params.allow_errors_num = format_settings.input_allow_errors_num; + params.allow_errors_ratio = format_settings.input_allow_errors_ratio; + + return input_getter(buf, sample, context, params, format_settings); +} + + +OutputFormatPtr FormatFactory::getOutputFormat(const String & name, WriteBuffer & buf, const Block & sample, const Context & context) const +{ + const auto & output_getter = getProcessorCreators(name).second; + if (!output_getter) + throw Exception("Format " + name + " is not suitable for output", ErrorCodes::FORMAT_IS_NOT_SUITABLE_FOR_OUTPUT); + + const Settings & settings = context.getSettingsRef(); + FormatSettings format_settings = getOutputFormatSetting(settings); + + /** TODO: Materialization is needed, because formats can use the functions `IDataType`, + * which only work with full columns. + */ + return output_getter(buf, sample, context, format_settings); +} + + void FormatFactory::registerInputFormat(const String & name, InputCreator input_creator) { auto & target = dict[name].first; if (target) throw Exception("FormatFactory: Input format " + name + " is already registered", ErrorCodes::LOGICAL_ERROR); - target = input_creator; + target = std::move(input_creator); } void FormatFactory::registerOutputFormat(const String & name, OutputCreator output_creator) @@ -94,7 +157,23 @@ void FormatFactory::registerOutputFormat(const String & name, OutputCreator outp auto & target = dict[name].second; if (target) throw Exception("FormatFactory: Output format " + name + " is already registered", ErrorCodes::LOGICAL_ERROR); - target = output_creator; + target = std::move(output_creator); +} + +void FormatFactory::registerInputFormatProcessor(const String & name, InputProcessorCreator input_creator) +{ + auto & target = processors_dict[name].first; + if (target) + throw Exception("FormatFactory: Input format " + name + " is already registered", ErrorCodes::LOGICAL_ERROR); + target = std::move(input_creator); +} + +void FormatFactory::registerOutputFormatProcessor(const String & name, OutputProcessorCreator output_creator) +{ + auto & target = processors_dict[name].second; + if (target) + throw Exception("FormatFactory: Output format " + name + " is already registered", ErrorCodes::LOGICAL_ERROR); + target = std::move(output_creator); } @@ -119,6 +198,25 @@ void registerOutputFormatParquet(FormatFactory & factory); void registerInputFormatProtobuf(FormatFactory & factory); void registerOutputFormatProtobuf(FormatFactory & factory); +void registerInputFormatProcessorNative(FormatFactory & factory); +void registerOutputFormatProcessorNative(FormatFactory & factory); +void registerInputFormatProcessorRowBinary(FormatFactory & factory); +void registerOutputFormatProcessorRowBinary(FormatFactory & factory); +void registerInputFormatProcessorTabSeparated(FormatFactory & factory); +void registerOutputFormatProcessorTabSeparated(FormatFactory & factory); +void registerInputFormatProcessorValues(FormatFactory & factory); +void registerOutputFormatProcessorValues(FormatFactory & factory); +void registerInputFormatProcessorCSV(FormatFactory & factory); +void registerOutputFormatProcessorCSV(FormatFactory & factory); +void registerInputFormatProcessorTSKV(FormatFactory & factory); +void registerOutputFormatProcessorTSKV(FormatFactory & factory); +void registerInputFormatProcessorJSONEachRow(FormatFactory & factory); +void registerOutputFormatProcessorJSONEachRow(FormatFactory & factory); +void registerInputFormatProcessorParquet(FormatFactory & factory); +void registerOutputFormatProcessorParquet(FormatFactory & factory); +void registerInputFormatProcessorProtobuf(FormatFactory & factory); +void registerOutputFormatProcessorProtobuf(FormatFactory & factory); + /// Output only (presentational) formats. void registerOutputFormatPretty(FormatFactory & factory); @@ -133,9 +231,22 @@ void registerOutputFormatODBCDriver2(FormatFactory & factory); void registerOutputFormatNull(FormatFactory & factory); void registerOutputFormatMySQLWire(FormatFactory & factory); +void registerOutputFormatProcessorPretty(FormatFactory & factory); +void registerOutputFormatProcessorPrettyCompact(FormatFactory & factory); +void registerOutputFormatProcessorPrettySpace(FormatFactory & factory); +void registerOutputFormatProcessorVertical(FormatFactory & factory); +void registerOutputFormatProcessorJSON(FormatFactory & factory); +void registerOutputFormatProcessorJSONCompact(FormatFactory & factory); +void registerOutputFormatProcessorXML(FormatFactory & factory); +void registerOutputFormatProcessorODBCDriver(FormatFactory & factory); +void registerOutputFormatProcessorODBCDriver2(FormatFactory & factory); +void registerOutputFormatProcessorNull(FormatFactory & factory); +void registerOutputFormatProcessorMySQLWrite(FormatFactory & factory); + /// Input only formats. void registerInputFormatCapnProto(FormatFactory & factory); +void registerInputFormatProcessorCapnProto(FormatFactory & factory); FormatFactory::FormatFactory() @@ -160,6 +271,28 @@ FormatFactory::FormatFactory() registerInputFormatParquet(*this); registerOutputFormatParquet(*this); + registerOutputFormatMySQLWire(*this); + + registerInputFormatProcessorNative(*this); + registerOutputFormatProcessorNative(*this); + registerInputFormatProcessorRowBinary(*this); + registerOutputFormatProcessorRowBinary(*this); + registerInputFormatProcessorTabSeparated(*this); + registerOutputFormatProcessorTabSeparated(*this); + registerInputFormatProcessorValues(*this); + registerOutputFormatProcessorValues(*this); + registerInputFormatProcessorCSV(*this); + registerOutputFormatProcessorCSV(*this); + registerInputFormatProcessorTSKV(*this); + registerOutputFormatProcessorTSKV(*this); + registerInputFormatProcessorJSONEachRow(*this); + registerOutputFormatProcessorJSONEachRow(*this); + registerInputFormatProcessorProtobuf(*this); + registerOutputFormatProcessorProtobuf(*this); + registerInputFormatProcessorCapnProto(*this); + registerInputFormatProcessorParquet(*this); + registerOutputFormatProcessorParquet(*this); + registerOutputFormatPretty(*this); registerOutputFormatPrettyCompact(*this); registerOutputFormatPrettySpace(*this); @@ -170,7 +303,18 @@ FormatFactory::FormatFactory() registerOutputFormatODBCDriver(*this); registerOutputFormatODBCDriver2(*this); registerOutputFormatNull(*this); - registerOutputFormatMySQLWire(*this); + + registerOutputFormatProcessorPretty(*this); + registerOutputFormatProcessorPrettyCompact(*this); + registerOutputFormatProcessorPrettySpace(*this); + registerOutputFormatProcessorVertical(*this); + registerOutputFormatProcessorJSON(*this); + registerOutputFormatProcessorJSONCompact(*this); + registerOutputFormatProcessorXML(*this); + registerOutputFormatProcessorODBCDriver(*this); + registerOutputFormatProcessorODBCDriver2(*this); + registerOutputFormatProcessorNull(*this); + registerOutputFormatProcessorMySQLWrite(*this); } } diff --git a/dbms/src/Formats/FormatFactory.h b/dbms/src/Formats/FormatFactory.h index 843d866301d..5cc1fcecb93 100644 --- a/dbms/src/Formats/FormatFactory.h +++ b/dbms/src/Formats/FormatFactory.h @@ -19,11 +19,28 @@ struct FormatSettings; class ReadBuffer; class WriteBuffer; +class IProcessor; +using ProcessorPtr = std::shared_ptr; + +class IInputFormat; +class IOutputFormat; + +struct RowInputFormatParams; + +using InputFormatPtr = std::shared_ptr; +using OutputFormatPtr = std::shared_ptr; + + /** Allows to create an IBlockInputStream or IBlockOutputStream by the name of the format. * Note: format and compression are independent things. */ class FormatFactory final : public ext::singleton { +public: + /// This callback allows to perform some additional actions after reading a single row. + /// It's initial purpose was to extract payload for virtual columns from Kafka Consumer ReadBuffer. + using ReadCallback = std::function; + private: using InputCreator = std::function; using OutputCreator = std::function; + using InputProcessorCreator = std::function; + + using OutputProcessorCreator = std::function; + using Creators = std::pair; + using ProcessorCreators = std::pair; using FormatsDictionary = std::unordered_map; + using FormatProcessorsDictionary = std::unordered_map; public: - BlockInputStreamPtr getInput(const String & name, ReadBuffer & buf, - const Block & sample, const Context & context, UInt64 max_block_size, UInt64 rows_portion_size = 0) const; + BlockInputStreamPtr getInput( + const String & name, + ReadBuffer & buf, + const Block & sample, + const Context & context, + UInt64 max_block_size, + UInt64 rows_portion_size = 0, + ReadCallback callback = {}) const; BlockOutputStreamPtr getOutput(const String & name, WriteBuffer & buf, const Block & sample, const Context & context) const; + InputFormatPtr getInputFormat(const String & name, ReadBuffer & buf, + const Block & sample, const Context & context, UInt64 max_block_size) const; + + OutputFormatPtr getOutputFormat(const String & name, WriteBuffer & buf, + const Block & sample, const Context & context) const; + /// Register format by its name. void registerInputFormat(const String & name, InputCreator input_creator); void registerOutputFormat(const String & name, OutputCreator output_creator); + void registerInputFormatProcessor(const String & name, InputProcessorCreator input_creator); + void registerOutputFormatProcessor(const String & name, OutputProcessorCreator output_creator); + const FormatsDictionary & getAllFormats() const { return dict; @@ -61,11 +109,13 @@ public: private: FormatsDictionary dict; + FormatProcessorsDictionary processors_dict; FormatFactory(); friend class ext::singleton; const Creators & getCreators(const String & name) const; + const ProcessorCreators & getProcessorCreators(const String & name) const; }; } diff --git a/dbms/src/Formats/JSONEachRowRowInputStream.cpp b/dbms/src/Formats/JSONEachRowRowInputStream.cpp index 5055d6c0c7d..72acf722ae7 100644 --- a/dbms/src/Formats/JSONEachRowRowInputStream.cpp +++ b/dbms/src/Formats/JSONEachRowRowInputStream.cpp @@ -260,11 +260,12 @@ void registerInputFormatJSONEachRow(FormatFactory & factory) const Context &, UInt64 max_block_size, UInt64 rows_portion_size, + FormatFactory::ReadCallback callback, const FormatSettings & settings) { return std::make_shared( std::make_shared(buf, sample, settings), - sample, max_block_size, rows_portion_size, settings); + sample, max_block_size, rows_portion_size, callback, settings); }); } diff --git a/dbms/src/Formats/NativeFormat.cpp b/dbms/src/Formats/NativeFormat.cpp index 88e727fdd3f..f324879608b 100644 --- a/dbms/src/Formats/NativeFormat.cpp +++ b/dbms/src/Formats/NativeFormat.cpp @@ -14,6 +14,7 @@ void registerInputFormatNative(FormatFactory & factory) const Context &, UInt64 /* max_block_size */, UInt64 /* min_read_rows */, + FormatFactory::ReadCallback /* callback */, const FormatSettings &) { return std::make_shared(buf, sample, 0); diff --git a/dbms/src/Formats/ParquetBlockInputStream.cpp b/dbms/src/Formats/ParquetBlockInputStream.cpp index 5e7dc876244..deba953bab4 100644 --- a/dbms/src/Formats/ParquetBlockInputStream.cpp +++ b/dbms/src/Formats/ParquetBlockInputStream.cpp @@ -476,6 +476,7 @@ void registerInputFormatParquet(FormatFactory & factory) const Context & context, UInt64 /* max_block_size */, UInt64 /* rows_portion_size */, + FormatFactory::ReadCallback /* callback */, const FormatSettings & /* settings */) { return std::make_shared(buf, sample, context); }); } diff --git a/dbms/src/Formats/ProtobufReader.cpp b/dbms/src/Formats/ProtobufReader.cpp index 2c0ea1251f4..54e8a050316 100644 --- a/dbms/src/Formats/ProtobufReader.cpp +++ b/dbms/src/Formats/ProtobufReader.cpp @@ -42,7 +42,7 @@ namespace Int64 decodeZigZag(UInt64 n) { return static_cast((n >> 1) ^ (~(n & 1) + 1)); } - void unknownFormat() + [[noreturn]] void unknownFormat() { throw Exception("Protobuf messages are corrupted or don't match the provided schema. Please note that Protobuf stream is length-delimited: every message is prefixed by its length in varint.", ErrorCodes::UNKNOWN_PROTOBUF_FORMAT); } diff --git a/dbms/src/Formats/ProtobufRowInputStream.cpp b/dbms/src/Formats/ProtobufRowInputStream.cpp index 45ea6b8dca7..1c4193b9f1a 100644 --- a/dbms/src/Formats/ProtobufRowInputStream.cpp +++ b/dbms/src/Formats/ProtobufRowInputStream.cpp @@ -74,11 +74,12 @@ void registerInputFormatProtobuf(FormatFactory & factory) const Context & context, UInt64 max_block_size, UInt64 rows_portion_size, + FormatFactory::ReadCallback callback, const FormatSettings & settings) { return std::make_shared( std::make_shared(buf, sample, FormatSchemaInfo(context, "Protobuf")), - sample, max_block_size, rows_portion_size, settings); + sample, max_block_size, rows_portion_size, callback, settings); }); } diff --git a/dbms/src/Formats/TSKVRowInputStream.cpp b/dbms/src/Formats/TSKVRowInputStream.cpp index ac89d5ec1c5..d86ee22bc4b 100644 --- a/dbms/src/Formats/TSKVRowInputStream.cpp +++ b/dbms/src/Formats/TSKVRowInputStream.cpp @@ -199,11 +199,12 @@ void registerInputFormatTSKV(FormatFactory & factory) const Context &, UInt64 max_block_size, UInt64 rows_portion_size, + FormatFactory::ReadCallback callback, const FormatSettings & settings) { return std::make_shared( std::make_shared(buf, sample, settings), - sample, max_block_size, rows_portion_size, settings); + sample, max_block_size, rows_portion_size, callback, settings); }); } diff --git a/dbms/src/Formats/TabSeparatedRowInputStream.cpp b/dbms/src/Formats/TabSeparatedRowInputStream.cpp index b9428e81c62..0c16c14e306 100644 --- a/dbms/src/Formats/TabSeparatedRowInputStream.cpp +++ b/dbms/src/Formats/TabSeparatedRowInputStream.cpp @@ -457,11 +457,12 @@ void registerInputFormatTabSeparated(FormatFactory & factory) const Context &, UInt64 max_block_size, UInt64 rows_portion_size, + FormatFactory::ReadCallback callback, const FormatSettings & settings) { return std::make_shared( std::make_shared(buf, sample, false, false, settings), - sample, max_block_size, rows_portion_size, settings); + sample, max_block_size, rows_portion_size, callback, settings); }); } @@ -473,11 +474,12 @@ void registerInputFormatTabSeparated(FormatFactory & factory) const Context &, UInt64 max_block_size, UInt64 rows_portion_size, + FormatFactory::ReadCallback callback, const FormatSettings & settings) { return std::make_shared( std::make_shared(buf, sample, true, false, settings), - sample, max_block_size, rows_portion_size, settings); + sample, max_block_size, rows_portion_size, callback, settings); }); } @@ -489,11 +491,12 @@ void registerInputFormatTabSeparated(FormatFactory & factory) const Context &, UInt64 max_block_size, UInt64 rows_portion_size, + FormatFactory::ReadCallback callback, const FormatSettings & settings) { return std::make_shared( std::make_shared(buf, sample, true, true, settings), - sample, max_block_size, rows_portion_size, settings); + sample, max_block_size, rows_portion_size, callback, settings); }); } } diff --git a/dbms/src/Formats/ValuesRowInputStream.cpp b/dbms/src/Formats/ValuesRowInputStream.cpp index b2d972d678b..33799a95549 100644 --- a/dbms/src/Formats/ValuesRowInputStream.cpp +++ b/dbms/src/Formats/ValuesRowInputStream.cpp @@ -156,11 +156,12 @@ void registerInputFormatValues(FormatFactory & factory) const Context & context, UInt64 max_block_size, UInt64 rows_portion_size, + FormatFactory::ReadCallback callback, const FormatSettings & settings) { return std::make_shared( std::make_shared(buf, sample, context, settings), - sample, max_block_size, rows_portion_size, settings); + sample, max_block_size, rows_portion_size, callback, settings); }); } diff --git a/dbms/src/Formats/tests/block_row_transforms.cpp b/dbms/src/Formats/tests/block_row_transforms.cpp index c880ff7fc39..9d38a37f833 100644 --- a/dbms/src/Formats/tests/block_row_transforms.cpp +++ b/dbms/src/Formats/tests/block_row_transforms.cpp @@ -45,7 +45,7 @@ try FormatSettings format_settings; RowInputStreamPtr row_input = std::make_shared(in_buf, sample, false, false, format_settings); - BlockInputStreamFromRowInputStream block_input(row_input, sample, DEFAULT_INSERT_BLOCK_SIZE, 0, format_settings); + BlockInputStreamFromRowInputStream block_input(row_input, sample, DEFAULT_INSERT_BLOCK_SIZE, 0, []{}, format_settings); RowOutputStreamPtr row_output = std::make_shared(out_buf, sample, false, false, format_settings); BlockOutputStreamFromRowOutputStream block_output(row_output, sample); diff --git a/dbms/src/Formats/tests/tab_separated_streams.cpp b/dbms/src/Formats/tests/tab_separated_streams.cpp index 50b9350d4c5..11895699c3b 100644 --- a/dbms/src/Formats/tests/tab_separated_streams.cpp +++ b/dbms/src/Formats/tests/tab_separated_streams.cpp @@ -42,7 +42,7 @@ try RowInputStreamPtr row_input = std::make_shared(in_buf, sample, false, false, format_settings); RowOutputStreamPtr row_output = std::make_shared(out_buf, sample, false, false, format_settings); - BlockInputStreamFromRowInputStream block_input(row_input, sample, DEFAULT_INSERT_BLOCK_SIZE, 0, format_settings); + BlockInputStreamFromRowInputStream block_input(row_input, sample, DEFAULT_INSERT_BLOCK_SIZE, 0, []{}, format_settings); BlockOutputStreamFromRowOutputStream block_output(row_output, sample); copyData(block_input, block_output); diff --git a/dbms/src/Functions/CMakeLists.txt b/dbms/src/Functions/CMakeLists.txt index 72e2ee5aeea..13b294197cf 100644 --- a/dbms/src/Functions/CMakeLists.txt +++ b/dbms/src/Functions/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(clickhouse_functions ${clickhouse_functions_sources}) target_link_libraries(clickhouse_functions PUBLIC clickhouse_dictionaries + clickhouse_dictionaries_embedded dbms ${CONSISTENT_HASHING_LIBRARY} consistent-hashing-sumbur @@ -19,6 +20,9 @@ target_link_libraries(clickhouse_functions ${METROHASH_LIBRARIES} murmurhash ${BASE64_LIBRARY} + + PRIVATE + ${Boost_FILESYSTEM_LIBRARY} ) if (OPENSSL_CRYPTO_LIBRARY) @@ -65,6 +69,11 @@ if(USE_XXHASH) target_include_directories(clickhouse_functions SYSTEM PRIVATE ${XXHASH_INCLUDE_DIR}) endif() +if (USE_H3) + target_link_libraries(clickhouse_functions PRIVATE ${H3_LIBRARY}) + target_include_directories(clickhouse_functions SYSTEM PRIVATE ${H3_INCLUDE_DIR}) +endif() + if(USE_HYPERSCAN) target_link_libraries(clickhouse_functions PRIVATE ${HYPERSCAN_LIBRARY}) target_include_directories(clickhouse_functions SYSTEM PRIVATE ${HYPERSCAN_INCLUDE_DIR}) diff --git a/dbms/src/Functions/CRC32.cpp b/dbms/src/Functions/CRC32.cpp index 95b93701783..80e0f163571 100644 --- a/dbms/src/Functions/CRC32.cpp +++ b/dbms/src/Functions/CRC32.cpp @@ -41,7 +41,7 @@ struct CRC32Impl } } - static void array(const ColumnString::Offsets & /*offsets*/, PaddedPODArray & /*res*/) + [[noreturn]] static void array(const ColumnString::Offsets & /*offsets*/, PaddedPODArray & /*res*/) { throw Exception("Cannot apply function CRC32 to Array argument", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } diff --git a/dbms/src/Functions/CustomWeekTransforms.h b/dbms/src/Functions/CustomWeekTransforms.h new file mode 100644 index 00000000000..88d341e5906 --- /dev/null +++ b/dbms/src/Functions/CustomWeekTransforms.h @@ -0,0 +1,137 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +/// The default mode value to use for the WEEK() function +#define DEFAULT_WEEK_MODE 0 + +namespace DB +{ +namespace ErrorCodes +{ + extern const int ILLEGAL_TYPE_OF_ARGUMENT; + extern const int ILLEGAL_COLUMN; +} + +/** + * CustomWeek Transformations. + */ + +static inline UInt32 dateIsNotSupported(const char * name) +{ + throw Exception("Illegal type Date of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); +} + +/// This factor transformation will say that the function is monotone everywhere. +struct ZeroTransform +{ + static inline UInt16 execute(UInt32, UInt8, const DateLUTImpl &) { return 0; } + static inline UInt16 execute(UInt16, UInt8, const DateLUTImpl &) { return 0; } +}; + +struct ToWeekImpl +{ + static constexpr auto name = "toWeek"; + + static inline UInt8 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone) + { + YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode); + return yw.second; + } + static inline UInt8 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone) + { + YearWeek yw = time_zone.toYearWeek(DayNum(d), week_mode); + return yw.second; + } + + using FactorTransform = ZeroTransform; +}; + +struct ToYearWeekImpl +{ + static constexpr auto name = "toYearWeek"; + + static inline UInt32 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone) + { + YearWeek yw = time_zone.toYearWeek(time_zone.toDayNum(t), week_mode | static_cast(WeekModeFlag::YEAR)); + return yw.first * 100 + yw.second; + } + static inline UInt32 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone) + { + YearWeek yw = time_zone.toYearWeek(DayNum(d), week_mode | static_cast(WeekModeFlag::YEAR)); + return yw.first * 100 + yw.second; + } + + using FactorTransform = ZeroTransform; +}; + +struct ToStartOfWeekImpl +{ + static constexpr auto name = "toStartOfWeek"; + + static inline UInt16 execute(UInt32 t, UInt8 week_mode, const DateLUTImpl & time_zone) + { + return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode); + } + static inline UInt16 execute(UInt16 d, UInt8 week_mode, const DateLUTImpl & time_zone) + { + return time_zone.toFirstDayNumOfWeek(DayNum(d), week_mode); + } + + using FactorTransform = ZeroTransform; +}; + +template +struct Transformer +{ + static void + vector(const PaddedPODArray & vec_from, PaddedPODArray & vec_to, UInt8 week_mode, const DateLUTImpl & time_zone) + { + size_t size = vec_from.size(); + vec_to.resize(size); + + for (size_t i = 0; i < size; ++i) + vec_to[i] = Transform::execute(vec_from[i], week_mode, time_zone); + } +}; + + +template +struct CustomWeekTransformImpl +{ + static void execute(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) + { + using Op = Transformer; + + UInt8 week_mode = DEFAULT_WEEK_MODE; + if (arguments.size() > 1) + { + if (const auto week_mode_column = checkAndGetColumnConst(block.getByPosition(arguments[1]).column.get())) + week_mode = week_mode_column->getValue(); + } + + const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(block, arguments, 2, 0); + const ColumnPtr source_col = block.getByPosition(arguments[0]).column; + if (const auto * sources = checkAndGetColumn>(source_col.get())) + { + auto col_to = ColumnVector::create(); + Op::vector(sources->getData(), col_to->getData(), week_mode, time_zone); + block.getByPosition(result).column = std::move(col_to); + } + else + { + throw Exception( + "Illegal column " + block.getByPosition(arguments[0]).column->getName() + " of first argument of function " + + Transform::name, + ErrorCodes::ILLEGAL_COLUMN); + } + } +}; + +} diff --git a/dbms/src/Functions/FunctionBinaryArithmetic.h b/dbms/src/Functions/FunctionBinaryArithmetic.h index 9faa2ee51e6..c2f92f0a77d 100644 --- a/dbms/src/Functions/FunctionBinaryArithmetic.h +++ b/dbms/src/Functions/FunctionBinaryArithmetic.h @@ -1,5 +1,10 @@ #pragma once +// Include this first, because `#define _asan_poison_address` from +// llvm/Support/Compiler.h conflicts with its forward declaration in +// sanitizer/asan_interface.h +#include + #include #include #include @@ -18,7 +23,6 @@ #include "castTypeToEither.h" #include "FunctionFactory.h" #include -#include #include #if USE_EMBEDDED_COMPILER @@ -538,12 +542,12 @@ class FunctionBinaryArithmetic : public IFunction if (WhichDataType(block.getByPosition(new_arguments[1]).type).isAggregateFunction()) std::swap(new_arguments[0], new_arguments[1]); - if (!block.getByPosition(new_arguments[1]).column->isColumnConst()) + if (!isColumnConst(*block.getByPosition(new_arguments[1]).column)) throw Exception{"Illegal column " + block.getByPosition(new_arguments[1]).column->getName() + " of argument of aggregation state multiply. Should be integer constant", ErrorCodes::ILLEGAL_COLUMN}; const IColumn & agg_state_column = *block.getByPosition(new_arguments[0]).column; - bool agg_state_is_const = agg_state_column.isColumnConst(); + bool agg_state_is_const = isColumnConst(agg_state_column); const ColumnAggregateFunction & column = typeid_cast( agg_state_is_const ? static_cast(agg_state_column).getDataColumn() : agg_state_column); @@ -600,8 +604,8 @@ class FunctionBinaryArithmetic : public IFunction const IColumn & lhs_column = *block.getByPosition(arguments[0]).column; const IColumn & rhs_column = *block.getByPosition(arguments[1]).column; - bool lhs_is_const = lhs_column.isColumnConst(); - bool rhs_is_const = rhs_column.isColumnConst(); + bool lhs_is_const = isColumnConst(lhs_column); + bool rhs_is_const = isColumnConst(rhs_column); const ColumnAggregateFunction & lhs = typeid_cast( lhs_is_const ? static_cast(lhs_column).getDataColumn() : lhs_column); diff --git a/dbms/src/Functions/FunctionCustomWeekToSomething.h b/dbms/src/Functions/FunctionCustomWeekToSomething.h new file mode 100644 index 00000000000..1a4cc26a456 --- /dev/null +++ b/dbms/src/Functions/FunctionCustomWeekToSomething.h @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include +#include + + +namespace DB +{ +namespace ErrorCodes +{ + extern const int ILLEGAL_TYPE_OF_ARGUMENT; + extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; +} + + +/// See CustomWeekTransforms.h +template +class FunctionCustomWeekToSomething : public IFunction +{ +public: + static constexpr auto name = Transform::name; + static FunctionPtr create(const Context &) { return std::make_shared(); } + + String getName() const override { return name; } + + bool isVariadic() const override { return true; } + size_t getNumberOfArguments() const override { return 0; } + + DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override + { + if (arguments.size() == 1) + { + if (!isDateOrDateTime(arguments[0].type)) + throw Exception( + "Illegal type " + arguments[0].type->getName() + " of argument of function " + getName() + + ". Should be a date or a date with time", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + } + else if (arguments.size() == 2) + { + if (!isDateOrDateTime(arguments[0].type)) + throw Exception( + "Illegal type " + arguments[0].type->getName() + " of argument of function " + getName() + + ". Should be a date or a date with time", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + if (!isUInt8(arguments[1].type)) + throw Exception( + "Function " + getName() + + " supports 1 or 2 or 3 arguments. The 1st argument " + "must be of type Date or DateTime. The 2nd argument (optional) must be " + "a constant UInt8 with week mode. The 3nd argument (optional) must be " + "a constant string with timezone name", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + } + else if (arguments.size() == 3) + { + if (!isDateOrDateTime(arguments[0].type)) + throw Exception( + "Illegal type " + arguments[0].type->getName() + " of argument of function " + getName() + + ". Should be a date or a date with time", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + if (!isUInt8(arguments[1].type)) + throw Exception( + "Function " + getName() + + " supports 1 or 2 or 3 arguments. The 1st argument " + "must be of type Date or DateTime. The 2nd argument (optional) must be " + "a constant UInt8 with week mode. The 3nd argument (optional) must be " + "a constant string with timezone name", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + if (!isString(arguments[2].type)) + throw Exception( + "Function " + getName() + + " supports 1 or 2 or 3 arguments. The 1st argument " + "must be of type Date or DateTime. The 2nd argument (optional) must be " + "a constant UInt8 with week mode. The 3nd argument (optional) must be " + "a constant string with timezone name", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + if (isDate(arguments[0].type) && std::is_same_v) + throw Exception( + "The timezone argument of function " + getName() + " is allowed only when the 1st argument has the type DateTime", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + } + else + throw Exception( + "Number of arguments for function " + getName() + " doesn't match: passed " + toString(arguments.size()) + + ", should be 1 or 2 or 3", + ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); + + return std::make_shared(); + } + + bool useDefaultImplementationForConstants() const override { return true; } + ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1, 2}; } + + void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override + { + const IDataType * from_type = block.getByPosition(arguments[0]).type.get(); + WhichDataType which(from_type); + + if (which.isDate()) + CustomWeekTransformImpl::execute( + block, arguments, result, input_rows_count); + else if (which.isDateTime()) + CustomWeekTransformImpl::execute( + block, arguments, result, input_rows_count); + else + throw Exception( + "Illegal type " + block.getByPosition(arguments[0]).type->getName() + " of argument of function " + getName(), + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + } + + + bool hasInformationAboutMonotonicity() const override { return true; } + + Monotonicity getMonotonicityForRange(const IDataType & type, const Field & left, const Field & right) const override + { + IFunction::Monotonicity is_monotonic{true}; + IFunction::Monotonicity is_not_monotonic; + + if (std::is_same_v) + { + is_monotonic.is_always_monotonic = true; + return is_monotonic; + } + + /// This method is called only if the function has one argument. Therefore, we do not care about the non-local time zone. + const DateLUTImpl & date_lut = DateLUT::instance(); + + if (left.isNull() || right.isNull()) + return is_not_monotonic; + + /// The function is monotonous on the [left, right] segment, if the factor transformation returns the same values for them. + + if (checkAndGetDataType(&type)) + { + return Transform::FactorTransform::execute(UInt16(left.get()), DEFAULT_WEEK_MODE, date_lut) + == Transform::FactorTransform::execute(UInt16(right.get()), DEFAULT_WEEK_MODE, date_lut) + ? is_monotonic + : is_not_monotonic; + } + else + { + return Transform::FactorTransform::execute(UInt32(left.get()), DEFAULT_WEEK_MODE, date_lut) + == Transform::FactorTransform::execute(UInt32(right.get()), DEFAULT_WEEK_MODE, date_lut) + ? is_monotonic + : is_not_monotonic; + } + } +}; + +} diff --git a/dbms/src/Functions/FunctionHelpers.cpp b/dbms/src/Functions/FunctionHelpers.cpp index 42fcebd5848..1f85b062b85 100644 --- a/dbms/src/Functions/FunctionHelpers.cpp +++ b/dbms/src/Functions/FunctionHelpers.cpp @@ -19,7 +19,7 @@ namespace ErrorCodes const ColumnConst * checkAndGetColumnConstStringOrFixedString(const IColumn * column) { - if (!column->isColumnConst()) + if (!isColumnConst(*column)) return {}; const ColumnConst * res = static_cast(column); @@ -64,17 +64,14 @@ static Block createBlockWithNestedColumnsImpl(const Block & block, const std::un { res.insert({nullptr, nested_type, col.name}); } - else if (col.column->isColumnNullable()) + else if (auto * nullable = checkAndGetColumn(*col.column)) { - const auto & nested_col = static_cast(*col.column).getNestedColumnPtr(); - + const auto & nested_col = nullable->getNestedColumnPtr(); res.insert({nested_col, nested_type, col.name}); } - else if (col.column->isColumnConst()) + else if (auto * const_column = checkAndGetColumn(*col.column)) { - const auto & nested_col = static_cast( - static_cast(*col.column).getDataColumn()).getNestedColumnPtr(); - + const auto & nested_col = checkAndGetColumn(const_column->getDataColumn())->getNestedColumnPtr(); res.insert({ ColumnConst::create(nested_col, col.column->size()), nested_type, col.name}); } else diff --git a/dbms/src/Functions/FunctionHelpers.h b/dbms/src/Functions/FunctionHelpers.h index 8e1efd113f8..2d5e77b10b8 100644 --- a/dbms/src/Functions/FunctionHelpers.h +++ b/dbms/src/Functions/FunctionHelpers.h @@ -22,23 +22,10 @@ const Type * checkAndGetDataType(const IDataType * data_type) return typeid_cast(data_type); } -template -const Type * checkAndGetColumn(const IColumn * column) -{ - return typeid_cast(column); -} - -template -bool checkColumn(const IColumn * column) -{ - return checkAndGetColumn(column); -} - - template const ColumnConst * checkAndGetColumnConst(const IColumn * column) { - if (!column || !column->isColumnConst()) + if (!column || !isColumnConst(*column)) return {}; const ColumnConst * res = static_cast(column); diff --git a/dbms/src/Functions/FunctionsBitmap.h b/dbms/src/Functions/FunctionsBitmap.h index e4696c69c3a..f64f04789cc 100644 --- a/dbms/src/Functions/FunctionsBitmap.h +++ b/dbms/src/Functions/FunctionsBitmap.h @@ -56,7 +56,7 @@ namespace ErrorCodes * * Two bitmap andnot calculation, return cardinality: * bitmapAndnotCardinality: bitmap,bitmap -> integer - * + * * Determine if a bitmap contains the given integer: * bitmapContains: bitmap,integer -> bool * @@ -432,28 +432,28 @@ private: Block & block, const ColumnNumbers & arguments, size_t input_rows_count, typename ColumnVector::Container & vec_to) { const IColumn * columns[2]; - bool isColumnConst[2]; + bool is_column_const[2]; const PaddedPODArray * container0; const PaddedPODArray * container1; for (size_t i = 0; i < 2; ++i) { columns[i] = block.getByPosition(arguments[i]).column.get(); - isColumnConst[i] = typeid_cast(columns[i])!=nullptr; + is_column_const[i] = isColumnConst(*columns[i]); } - if (isColumnConst[0]) + if (is_column_const[0]) container0 = &typeid_cast(typeid_cast(columns[0])->getDataColumnPtr().get())->getData(); else container0 = &typeid_cast(columns[0])->getData(); - if (isColumnConst[1]) + if (is_column_const[1]) container1 = &typeid_cast(typeid_cast(columns[1])->getDataColumnPtr().get())->getData(); else container1 = &typeid_cast(columns[1])->getData(); for (size_t i = 0; i < input_rows_count; ++i) { - const AggregateDataPtr dataPtr0 = isColumnConst[0] ? (*container0)[0] : (*container0)[i]; - const UInt32 data1 = isColumnConst[1] ? (*container1)[0] : (*container1)[i]; + const AggregateDataPtr dataPtr0 = is_column_const[0] ? (*container0)[0] : (*container0)[i]; + const UInt32 data1 = is_column_const[1] ? (*container1)[0] : (*container1)[i]; const AggregateFunctionGroupBitmapData& bd0 = *reinterpret_cast*>(dataPtr0); vec_to[i] = bd0.rbs.rb_contains(data1); @@ -529,18 +529,18 @@ private: Block & block, const ColumnNumbers & arguments, size_t input_rows_count, typename ColumnVector::Container & vec_to) { const ColumnAggregateFunction * columns[2]; - bool isColumnConst[2]; + bool is_column_const[2]; for (size_t i = 0; i < 2; ++i) { - if (auto argument_column_const = typeid_cast(block.getByPosition(arguments[i]).column.get())) + if (auto argument_column_const = checkAndGetColumn(block.getByPosition(arguments[i]).column.get())) { columns[i] = typeid_cast(argument_column_const->getDataColumnPtr().get()); - isColumnConst[i] = true; + is_column_const[i] = true; } else { columns[i] = typeid_cast(block.getByPosition(arguments[i]).column.get()); - isColumnConst[i] = false; + is_column_const[i] = false; } } @@ -549,8 +549,8 @@ private: for (size_t i = 0; i < input_rows_count; ++i) { - const AggregateDataPtr dataPtr0 = isColumnConst[0] ? container0[0] : container0[i]; - const AggregateDataPtr dataPtr1 = isColumnConst[1] ? container1[0] : container1[i]; + const AggregateDataPtr dataPtr0 = is_column_const[0] ? container0[0] : container0[i]; + const AggregateDataPtr dataPtr1 = is_column_const[1] ? container1[0] : container1[i]; const AggregateFunctionGroupBitmapData & bd1 = *reinterpret_cast*>(dataPtr0); const AggregateFunctionGroupBitmapData & bd2 diff --git a/dbms/src/Functions/FunctionsComparison.h b/dbms/src/Functions/FunctionsComparison.h index d399ef8ff48..2da3e0a8970 100644 --- a/dbms/src/Functions/FunctionsComparison.h +++ b/dbms/src/Functions/FunctionsComparison.h @@ -1032,8 +1032,8 @@ private: void executeGenericIdenticalTypes(Block & block, size_t result, const IColumn * c0, const IColumn * c1) { - bool c0_const = c0->isColumnConst(); - bool c1_const = c1->isColumnConst(); + bool c0_const = isColumnConst(*c0); + bool c1_const = isColumnConst(*c1); if (c0_const && c1_const) { diff --git a/dbms/src/Functions/FunctionsConsistentHashing.h b/dbms/src/Functions/FunctionsConsistentHashing.h index 7961395638f..b7282c10dba 100644 --- a/dbms/src/Functions/FunctionsConsistentHashing.h +++ b/dbms/src/Functions/FunctionsConsistentHashing.h @@ -133,7 +133,7 @@ public: void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override { - if (block.getByPosition(arguments[1]).column->isColumnConst()) + if (isColumnConst(*block.getByPosition(arguments[1]).column)) executeConstBuckets(block, arguments, result); else throw Exception( diff --git a/dbms/src/Functions/FunctionsExternalDictionaries.h b/dbms/src/Functions/FunctionsExternalDictionaries.h index 9ff77eb8d92..877d3e6f0f2 100644 --- a/dbms/src/Functions/FunctionsExternalDictionaries.h +++ b/dbms/src/Functions/FunctionsExternalDictionaries.h @@ -1894,7 +1894,7 @@ private: template static const PaddedPODArray & getColumnDataAsPaddedPODArray(const IColumn & column, PaddedPODArray & backup_storage) { - if (!column.isColumnConst()) + if (!isColumnConst(column)) { if (const auto vector_col = checkAndGetColumn>(&column)) { diff --git a/dbms/src/Functions/FunctionsExternalModels.cpp b/dbms/src/Functions/FunctionsExternalModels.cpp index 6c11cb78bb5..89418d8620e 100644 --- a/dbms/src/Functions/FunctionsExternalModels.cpp +++ b/dbms/src/Functions/FunctionsExternalModels.cpp @@ -92,7 +92,7 @@ void FunctionModelEvaluate::executeImpl(Block & block, const ColumnNumbers & arg materialized_columns.push_back(full_column); columns.back() = full_column.get(); } - if (auto * col_nullable = typeid_cast(columns.back())) + if (auto * col_nullable = checkAndGetColumn(*columns.back())) { if (!null_map) null_map = col_nullable->getNullMapColumnPtr(); diff --git a/dbms/src/Functions/FunctionsFindCluster.h b/dbms/src/Functions/FunctionsFindCluster.h index 75e859de3a5..8c85700e2bd 100644 --- a/dbms/src/Functions/FunctionsFindCluster.h +++ b/dbms/src/Functions/FunctionsFindCluster.h @@ -130,7 +130,7 @@ public: auto column_result = block.getByPosition(result).type->createColumn(); auto out_untyped = column_result.get(); - if (!centroids_array_untyped->isColumnConst()) + if (!isColumnConst(*centroids_array_untyped)) throw Exception{"Second argument of function " + getName() + " must be literal array", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT}; executeImplTyped(in_untyped, out_untyped, centroids_array_untyped); diff --git a/dbms/src/Functions/FunctionsHashing.h b/dbms/src/Functions/FunctionsHashing.h index ac98231e3e6..1b98191e224 100644 --- a/dbms/src/Functions/FunctionsHashing.h +++ b/dbms/src/Functions/FunctionsHashing.h @@ -1041,7 +1041,7 @@ private: void executeTwoArgs(Block & block, const ColumnNumbers & arguments, const size_t result) const { const auto level_col = block.getByPosition(arguments.back()).column.get(); - if (!level_col->isColumnConst()) + if (!isColumnConst(*level_col)) throw Exception{"Second argument of function " + getName() + " must be an integral constant", ErrorCodes::ILLEGAL_COLUMN}; const auto level = level_col->get64(0); diff --git a/dbms/src/Functions/FunctionsJSON.h b/dbms/src/Functions/FunctionsJSON.h index 5781ca4a9fb..a1826b22d30 100644 --- a/dbms/src/Functions/FunctionsJSON.h +++ b/dbms/src/Functions/FunctionsJSON.h @@ -213,7 +213,7 @@ private: + " should be a string specifying key or an integer specifying index, illegal type: " + column.type->getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT}; - if (column.column->isColumnConst()) + if (isColumnConst(*column.column)) { const auto & column_const = static_cast(*column.column); if (isString(column.type)) diff --git a/dbms/src/Functions/FunctionsLogical.h b/dbms/src/Functions/FunctionsLogical.h index 6a32307cf22..98843017a65 100644 --- a/dbms/src/Functions/FunctionsLogical.h +++ b/dbms/src/Functions/FunctionsLogical.h @@ -211,7 +211,7 @@ private: bool has_res = false; for (int i = static_cast(in.size()) - 1; i >= 0; --i) { - if (!in[i]->isColumnConst()) + if (!isColumnConst(*in[i])) continue; Field value = (*in[i])[0]; diff --git a/dbms/src/Functions/FunctionsRandom.cpp b/dbms/src/Functions/FunctionsRandom.cpp index ede8c332d18..19b2f08cdba 100644 --- a/dbms/src/Functions/FunctionsRandom.cpp +++ b/dbms/src/Functions/FunctionsRandom.cpp @@ -57,10 +57,10 @@ void RandImpl::execute(char * output, size_t size) for (const char * end = output + size; output < end; output += 16) { - unalignedStore(output, generator0.next()); - unalignedStore(output + 4, generator1.next()); - unalignedStore(output + 8, generator2.next()); - unalignedStore(output + 12, generator3.next()); + unalignedStore(output, generator0.next()); + unalignedStore(output + 4, generator1.next()); + unalignedStore(output + 8, generator2.next()); + unalignedStore(output + 12, generator3.next()); } /// It is guaranteed (by PaddedPODArray) that we can overwrite up to 15 bytes after end. diff --git a/dbms/src/Functions/FunctionsRound.h b/dbms/src/Functions/FunctionsRound.h index 0de944516d6..38b72274f5a 100644 --- a/dbms/src/Functions/FunctionsRound.h +++ b/dbms/src/Functions/FunctionsRound.h @@ -512,7 +512,7 @@ public: if (arguments.size() == 2) { const IColumn & scale_column = *block.getByPosition(arguments[1]).column; - if (!scale_column.isColumnConst()) + if (!isColumnConst(scale_column)) throw Exception("Scale argument for rounding functions must be constant.", ErrorCodes::ILLEGAL_COLUMN); Field scale_field = static_cast(scale_column).getField(); diff --git a/dbms/src/Functions/FunctionsStringRegex.cpp b/dbms/src/Functions/FunctionsStringRegex.cpp index ee619f20fdd..464260e6a33 100644 --- a/dbms/src/Functions/FunctionsStringRegex.cpp +++ b/dbms/src/Functions/FunctionsStringRegex.cpp @@ -814,7 +814,7 @@ public: const ColumnPtr column_needle = block.getByPosition(arguments[1]).column; const ColumnPtr column_replacement = block.getByPosition(arguments[2]).column; - if (!column_needle->isColumnConst() || !column_replacement->isColumnConst()) + if (!isColumnConst(*column_needle) || !isColumnConst(*column_replacement)) throw Exception("2nd and 3rd arguments of function " + getName() + " must be constants.", ErrorCodes::ILLEGAL_COLUMN); const IColumn * c1 = block.getByPosition(arguments[1]).column.get(); diff --git a/dbms/src/Functions/FunctionsStringSimilarity.cpp b/dbms/src/Functions/FunctionsStringSimilarity.cpp index 9a9dd01a972..d5632b136e4 100644 --- a/dbms/src/Functions/FunctionsStringSimilarity.cpp +++ b/dbms/src/Functions/FunctionsStringSimilarity.cpp @@ -271,11 +271,17 @@ struct NgramDistanceImpl { size_t first_size = dispatchSearcher(calculateHaystackStatsAndMetric, data.data(), data_size, common_stats, distance, nullptr); /// For !Symmetric version we should not use first_size. - res = distance * 1.f / std::max(Symmetric * first_size + second_size, size_t(1)); + if constexpr (Symmetric) + res = distance * 1.f / std::max(first_size + second_size, size_t(1)); + else + res = 1.f - distance * 1.f / std::max(second_size, size_t(1)); } else { - res = 1.f; + if constexpr (Symmetric) + res = 1.f; + else + res = 0.f; } } @@ -333,13 +339,19 @@ struct NgramDistanceImpl /// For !Symmetric version we should not use haystack_stats_size. - res[i] = distance * 1.f / std::max(Symmetric * haystack_stats_size + needle_stats_size, size_t(1)); + if constexpr (Symmetric) + res[i] = distance * 1.f / std::max(haystack_stats_size + needle_stats_size, size_t(1)); + else + res[i] = 1.f - distance * 1.f / std::max(needle_stats_size, size_t(1)); } else { /// Strings are too big, we are assuming they are not the same. This is done because of limiting number /// of bigrams added and not allocating too much memory. - res[i] = 1.f; + if constexpr (Symmetric) + res[i] = 1.f; + else + res[i] = 0.f; } prev_needle_offset = needle_offsets[i]; @@ -399,11 +411,11 @@ struct NgramDistanceImpl for (size_t j = 0; j < needle_stats_size; ++j) --common_stats[needle_ngram_storage[j]]; - res[i] = distance * 1.f / std::max(needle_stats_size, size_t(1)); + res[i] = 1.f - distance * 1.f / std::max(needle_stats_size, size_t(1)); } else { - res[i] = 1.f; + res[i] = 0.f; } prev_offset = needle_offsets[i]; @@ -446,12 +458,18 @@ struct NgramDistanceImpl distance, ngram_storage.get()); /// For !Symmetric version we should not use haystack_stats_size. - res[i] = distance * 1.f / std::max(Symmetric * haystack_stats_size + needle_stats_size, size_t(1)); + if constexpr (Symmetric) + res[i] = distance * 1.f / std::max(haystack_stats_size + needle_stats_size, size_t(1)); + else + res[i] = 1.f - distance * 1.f / std::max(needle_stats_size, size_t(1)); } else { /// if the strings are too big, we say they are completely not the same - res[i] = 1.f; + if constexpr (Symmetric) + res[i] = 1.f; + else + res[i] = 0.f; } distance = needle_stats_size; prev_offset = offsets[i]; diff --git a/dbms/src/Functions/FunctionsVisitParam.h b/dbms/src/Functions/FunctionsVisitParam.h index 09cc3106719..353dda930ef 100644 --- a/dbms/src/Functions/FunctionsVisitParam.h +++ b/dbms/src/Functions/FunctionsVisitParam.h @@ -91,8 +91,7 @@ struct ExtractBool struct ExtractRaw { - static constexpr size_t bytes_on_stack = 64; - using ExpectChars = PODArray, bytes_on_stack>>; + using ExpectChars = PODArrayWithStackMemory; static void extract(const UInt8 * pos, const UInt8 * end, ColumnString::Chars & res_data) { @@ -101,7 +100,7 @@ struct ExtractRaw for (auto extract_begin = pos; pos != end; ++pos) { - if (*pos == current_expect_end) + if (current_expect_end && *pos == current_expect_end) { expects_end.pop_back(); current_expect_end = expects_end.empty() ? 0 : expects_end.back(); @@ -193,7 +192,7 @@ struct ExtractParamImpl /// We check that the entry does not pass through the boundaries of strings. if (pos + needle.size() < begin + offsets[i]) - res[i] = ParamExtractor::extract(pos + needle.size(), begin + offsets[i]); + res[i] = ParamExtractor::extract(pos + needle.size(), begin + offsets[i] - 1); /// don't include terminating zero else res[i] = 0; diff --git a/dbms/src/Functions/GatherUtils/CMakeLists.txt b/dbms/src/Functions/GatherUtils/CMakeLists.txt index 20c92352c57..bcb02051774 100644 --- a/dbms/src/Functions/GatherUtils/CMakeLists.txt +++ b/dbms/src/Functions/GatherUtils/CMakeLists.txt @@ -1,7 +1,7 @@ include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake) add_headers_and_sources(clickhouse_functions_gatherutils .) add_library(clickhouse_functions_gatherutils ${clickhouse_functions_gatherutils_sources} ${clickhouse_functions_gatherutils_headers}) -target_link_libraries(clickhouse_functions_gatherutils PRIVATE clickhouse_common_io) +target_link_libraries(clickhouse_functions_gatherutils PRIVATE dbms) if (CMAKE_BUILD_TYPE_UC STREQUAL "RELEASE" OR CMAKE_BUILD_TYPE_UC STREQUAL "RELWITHDEBINFO" OR CMAKE_BUILD_TYPE_UC STREQUAL "MINSIZEREL") # Won't generate debug info for files with heavy template instantiation to achieve faster linking and lower size. diff --git a/dbms/src/Functions/GeoUtils.h b/dbms/src/Functions/GeoUtils.h index 731305cd705..b3a283ee2e6 100644 --- a/dbms/src/Functions/GeoUtils.h +++ b/dbms/src/Functions/GeoUtils.h @@ -224,9 +224,16 @@ void PointInPolygonWithGrid::calcGridAttributes( const Point & min_corner = box.min_corner(); const Point & max_corner = box.max_corner(); +#pragma GCC diagnostic push +#if !__clang__ +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + cell_width = (max_corner.x() - min_corner.x()) / grid_size; cell_height = (max_corner.y() - min_corner.y()) / grid_size; +#pragma GCC diagnostic pop + if (cell_width == 0 || cell_height == 0) { has_empty_bound = true; diff --git a/dbms/src/Functions/IFunction.cpp b/dbms/src/Functions/IFunction.cpp index f792c40f400..c05ece54e11 100644 --- a/dbms/src/Functions/IFunction.cpp +++ b/dbms/src/Functions/IFunction.cpp @@ -111,10 +111,10 @@ ColumnPtr wrapInNullable(const ColumnPtr & src, const Block & block, const Colum if (src->onlyNull()) return src; - else if (src->isColumnNullable()) + else if (auto * nullable = checkAndGetColumn(*src)) { - src_not_nullable = static_cast(*src).getNestedColumnPtr(); - result_null_map_column = static_cast(*src).getNullMapColumnPtr(); + src_not_nullable = nullable->getNestedColumnPtr(); + result_null_map_column = nullable->getNullMapColumnPtr(); } for (const auto & arg : args) @@ -127,12 +127,12 @@ ColumnPtr wrapInNullable(const ColumnPtr & src, const Block & block, const Colum if (elem.column->onlyNull()) return block.getByPosition(result).type->createColumnConst(input_rows_count, Null()); - if (elem.column->isColumnConst()) + if (isColumnConst(*elem.column)) continue; - if (elem.column->isColumnNullable()) + if (auto * nullable = checkAndGetColumn(*elem.column)) { - const ColumnPtr & null_map_column = static_cast(*elem.column).getNullMapColumnPtr(); + const ColumnPtr & null_map_column = nullable->getNullMapColumnPtr(); if (!result_null_map_column) { result_null_map_column = null_map_column; @@ -204,7 +204,7 @@ NullPresence getNullPresense(const ColumnsWithTypeAndName & args) bool allArgumentsAreConstants(const Block & block, const ColumnNumbers & args) { for (auto arg : args) - if (!block.getByPosition(arg).column->isColumnConst()) + if (!isColumnConst(*block.getByPosition(arg).column)) return false; return true; } @@ -217,7 +217,7 @@ bool PreparedFunctionImpl::defaultImplementationForConstantArguments(Block & blo /// Check that these arguments are really constant. for (auto arg_num : arguments_to_remain_constants) - if (arg_num < args.size() && !block.getByPosition(args[arg_num]).column->isColumnConst()) + if (arg_num < args.size() && !isColumnConst(*block.getByPosition(args[arg_num]).column)) throw Exception("Argument at index " + toString(arg_num) + " for function " + getName() + " must be constant", ErrorCodes::ILLEGAL_COLUMN); if (args.empty() || !useDefaultImplementationForConstants() || !allArgumentsAreConstants(block, args)) @@ -583,7 +583,7 @@ DataTypePtr FunctionBuilderImpl::getReturnType(const ColumnsWithTypeAndName & ar for (ColumnWithTypeAndName & arg : args_without_low_cardinality) { - bool is_const = arg.column && arg.column->isColumnConst(); + bool is_const = arg.column && isColumnConst(*arg.column); if (is_const) arg.column = static_cast(*arg.column).removeLowCardinality(); diff --git a/dbms/src/Functions/RapidJSONParser.h b/dbms/src/Functions/RapidJSONParser.h index 9ffa355b9a9..c88d61fb69d 100644 --- a/dbms/src/Functions/RapidJSONParser.h +++ b/dbms/src/Functions/RapidJSONParser.h @@ -22,8 +22,10 @@ struct RapidJSONParser bool parse(const StringRef & json) { - document.Parse(json.data); - return !document.HasParseError(); + rapidjson::MemoryStream ms(json.data, json.size); + rapidjson::EncodedInputStream, rapidjson::MemoryStream> is(ms); + document.ParseStream(is); + return !document.HasParseError() && (ms.Tell() == json.size); } struct Iterator diff --git a/dbms/src/Functions/SimdJSONParser.h b/dbms/src/Functions/SimdJSONParser.h index ef43e571635..dfa28ccfd56 100644 --- a/dbms/src/Functions/SimdJSONParser.h +++ b/dbms/src/Functions/SimdJSONParser.h @@ -7,18 +7,8 @@ #include #include -#ifdef __clang__ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wold-style-cast" - #pragma clang diagnostic ignored "-Wnewline-eof" -#endif - #include -#ifdef __clang__ - #pragma clang diagnostic pop -#endif - namespace DB { @@ -42,7 +32,7 @@ struct SimdJSONParser bool parse(const StringRef & json) { return !json_parse(json.data, json.size, pj); } - using Iterator = ParsedJson::iterator; + using Iterator = simdjson::ParsedJson::iterator; Iterator getRoot() { return Iterator{pj}; } static bool isInt64(const Iterator & it) { return it.is_integer(); } @@ -143,7 +133,7 @@ struct SimdJSONParser } private: - ParsedJson pj; + simdjson::ParsedJson pj; }; } diff --git a/dbms/src/Functions/URL/CMakeLists.txt b/dbms/src/Functions/URL/CMakeLists.txt index 5bad6dc89cb..54221b43cf6 100644 --- a/dbms/src/Functions/URL/CMakeLists.txt +++ b/dbms/src/Functions/URL/CMakeLists.txt @@ -1,8 +1,8 @@ include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake) add_headers_and_sources(clickhouse_functions_url .) add_library(clickhouse_functions_url ${clickhouse_functions_url_sources} ${clickhouse_functions_url_headers}) -target_link_libraries(clickhouse_functions_url PRIVATE clickhouse_common_io) -target_include_directories(clickhouse_functions_url PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../include) # ${CMAKE_CURRENT_BINARY_DIR}/include +target_link_libraries(clickhouse_functions_url PRIVATE dbms) +target_include_directories(clickhouse_functions_url PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../include) # ${CMAKE_CURRENT_BINARY_DIR}/include if (CMAKE_BUILD_TYPE_UC STREQUAL "RELEASE" OR CMAKE_BUILD_TYPE_UC STREQUAL "RELWITHDEBINFO" OR CMAKE_BUILD_TYPE_UC STREQUAL "MINSIZEREL") # Won't generate debug info for files with heavy template instantiation to achieve faster linking and lower size. diff --git a/dbms/src/Functions/URL/decodeURLComponent.cpp b/dbms/src/Functions/URL/decodeURLComponent.cpp index ee60498af69..008e3b0645f 100644 --- a/dbms/src/Functions/URL/decodeURLComponent.cpp +++ b/dbms/src/Functions/URL/decodeURLComponent.cpp @@ -89,7 +89,7 @@ struct DecodeURLComponentImpl res_data.resize(res_offset); } - static void vector_fixed(const ColumnString::Chars &, size_t, ColumnString::Chars &) + [[noreturn]] static void vector_fixed(const ColumnString::Chars &, size_t, ColumnString::Chars &) { throw Exception("Column of type FixedString is not supported by URL functions", ErrorCodes::ILLEGAL_COLUMN); } diff --git a/dbms/src/Functions/URL/domain.h b/dbms/src/Functions/URL/domain.h index 1a7b1df5291..141887d8e96 100644 --- a/dbms/src/Functions/URL/domain.h +++ b/dbms/src/Functions/URL/domain.h @@ -3,44 +3,117 @@ #include "protocol.h" #include #include - +#include namespace DB { +namespace +{ + +inline StringRef checkAndReturnHost(const Pos & pos, const Pos & dot_pos, const Pos & start_of_host) +{ + if (!dot_pos || start_of_host >= pos || pos - dot_pos == 1) + return StringRef{}; + + auto after_dot = *(dot_pos + 1); + if (after_dot == ':' || after_dot == '/' || after_dot == '?' || after_dot == '#') + return StringRef{}; + + return StringRef(start_of_host, pos - start_of_host); +} + +} + /// Extracts host from given url. inline StringRef getURLHost(const char * data, size_t size) { Pos pos = data; Pos end = data + size; - if (end == (pos = find_first_symbols<'/'>(pos, end))) - return {}; - - if (pos != data) + if (*pos == '/' && *(pos + 1) == '/') { - StringRef scheme = getURLScheme(data, size); - Pos scheme_end = data + scheme.size; - - // Colon must follows after scheme. - if (pos - scheme_end != 1 || *scheme_end != ':') - return {}; + pos += 2; + } + else + { + Pos scheme_end = data + std::min(size, 16UL); + for (++pos; pos < scheme_end; ++pos) + { + if (!isAlphaNumericASCII(*pos)) + { + switch (*pos) + { + case '.': + case '-': + case '+': + break; + case ' ': /// restricted symbols + case '\t': + case '<': + case '>': + case '%': + case '{': + case '}': + case '|': + case '\\': + case '^': + case '~': + case '[': + case ']': + case ';': + case '=': + case '&': + return StringRef{}; + default: + goto exloop; + } + } + } +exloop: if ((scheme_end - pos) > 2 && *pos == ':' && *(pos + 1) == '/' && *(pos + 2) == '/') + pos += 3; + else + pos = data; } - if (end - pos < 2 || *(pos) != '/' || *(pos + 1) != '/') - return {}; - pos += 2; - - const char * start_of_host = pos; + Pos dot_pos = nullptr; + auto start_of_host = pos; for (; pos < end; ++pos) { - if (*pos == '@') - start_of_host = pos + 1; - else if (*pos == ':' || *pos == '/' || *pos == '?' || *pos == '#') + switch (*pos) + { + case '.': + dot_pos = pos; break; + case ':': /// end symbols + case '/': + case '?': + case '#': + return checkAndReturnHost(pos, dot_pos, start_of_host); + case '@': /// myemail@gmail.com + start_of_host = pos + 1; + break; + case ' ': /// restricted symbols in whole URL + case '\t': + case '<': + case '>': + case '%': + case '{': + case '}': + case '|': + case '\\': + case '^': + case '~': + case '[': + case ']': + case ';': + case '=': + case '&': + return StringRef{}; + } } - return (pos == start_of_host) ? StringRef{} : StringRef(start_of_host, pos - start_of_host); + return checkAndReturnHost(pos, dot_pos, start_of_host); } template diff --git a/dbms/src/Functions/array/CMakeLists.txt b/dbms/src/Functions/array/CMakeLists.txt index 59ae693bb67..f826db1e817 100644 --- a/dbms/src/Functions/array/CMakeLists.txt +++ b/dbms/src/Functions/array/CMakeLists.txt @@ -1,7 +1,7 @@ include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake) add_headers_and_sources(clickhouse_functions_array .) add_library(clickhouse_functions_array ${clickhouse_functions_array_sources} ${clickhouse_functions_array_headers}) -target_link_libraries(clickhouse_functions_array PRIVATE clickhouse_common_io clickhouse_functions_gatherutils) +target_link_libraries(clickhouse_functions_array PRIVATE dbms clickhouse_functions_gatherutils) if (CMAKE_BUILD_TYPE_UC STREQUAL "RELEASE" OR CMAKE_BUILD_TYPE_UC STREQUAL "RELWITHDEBINFO" OR CMAKE_BUILD_TYPE_UC STREQUAL "MINSIZEREL") # Won't generate debug info for files with heavy template instantiation to achieve faster linking and lower size. diff --git a/dbms/src/Functions/array/arrayDistinct.cpp b/dbms/src/Functions/array/arrayDistinct.cpp index 18dd7be850a..173b0e1334c 100644 --- a/dbms/src/Functions/array/arrayDistinct.cpp +++ b/dbms/src/Functions/array/arrayDistinct.cpp @@ -100,13 +100,12 @@ void FunctionArrayDistinct::executeImpl(Block & block, const ColumnNumbers & arg IColumn & res_data = res.getData(); ColumnArray::Offsets & res_offsets = res.getOffsets(); - const ColumnNullable * nullable_col = nullptr; + const ColumnNullable * nullable_col = checkAndGetColumn(src_data); const IColumn * inner_col; - if (src_data.isColumnNullable()) + if (nullable_col) { - nullable_col = static_cast(&src_data); inner_col = &nullable_col->getNestedColumn(); } else diff --git a/dbms/src/Functions/array/arrayElement.cpp b/dbms/src/Functions/array/arrayElement.cpp index a4fce864d54..c9293da9433 100644 --- a/dbms/src/Functions/array/arrayElement.cpp +++ b/dbms/src/Functions/array/arrayElement.cpp @@ -749,12 +749,12 @@ void FunctionArrayElement::executeImpl(Block & block, const ColumnNumbers & argu col_array = checkAndGetColumn(block.getByPosition(arguments[0]).column.get()); if (col_array) - is_array_of_nullable = col_array->getData().isColumnNullable(); + is_array_of_nullable = isColumnNullable(col_array->getData()); else { col_const_array = checkAndGetColumnConstData(block.getByPosition(arguments[0]).column.get()); if (col_const_array) - is_array_of_nullable = col_const_array->getData().isColumnNullable(); + is_array_of_nullable = isColumnNullable(col_const_array->getData()); else throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName() + " of first argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN); @@ -836,7 +836,7 @@ void FunctionArrayElement::perform(Block & block, const ColumnNumbers & argument if (executeTuple(block, arguments, result, input_rows_count)) { } - else if (!block.getByPosition(arguments[1]).column->isColumnConst()) + else if (!isColumnConst(*block.getByPosition(arguments[1]).column)) { if (!(executeArgument(block, arguments, result, builder, input_rows_count) || executeArgument(block, arguments, result, builder, input_rows_count) diff --git a/dbms/src/Functions/array/arrayEnumerateExtended.h b/dbms/src/Functions/array/arrayEnumerateExtended.h index 72958574e83..0368c0b5249 100644 --- a/dbms/src/Functions/array/arrayEnumerateExtended.h +++ b/dbms/src/Functions/array/arrayEnumerateExtended.h @@ -157,14 +157,12 @@ void FunctionArrayEnumerateExtended::executeImpl(Block & block, const C for (size_t i = 0; i < num_arguments; ++i) { - if (data_columns[i]->isColumnNullable()) + if (auto * nullable_col = checkAndGetColumn(*data_columns[i])) { - const auto & nullable_col = static_cast(*data_columns[i]); - if (num_arguments == 1) - data_columns[i] = &nullable_col.getNestedColumn(); + data_columns[i] = &nullable_col->getNestedColumn(); - null_map = &nullable_col.getNullMapData(); + null_map = &nullable_col->getNullMapData(); break; } } diff --git a/dbms/src/Functions/array/arrayEnumerateRanked.cpp b/dbms/src/Functions/array/arrayEnumerateRanked.cpp index a559d64c9a0..c148664b664 100644 --- a/dbms/src/Functions/array/arrayEnumerateRanked.cpp +++ b/dbms/src/Functions/array/arrayEnumerateRanked.cpp @@ -47,7 +47,7 @@ ArraysDepths getArraysDepths(const ColumnsWithTypeAndName & arguments) { const auto & depth_column = arguments[i].column; - if (depth_column && depth_column->isColumnConst()) + if (depth_column && isColumnConst(*depth_column)) { UInt64 value = static_cast(*depth_column).getValue(); if (!value) diff --git a/dbms/src/Functions/array/arrayIndex.h b/dbms/src/Functions/array/arrayIndex.h index 97df807a270..12a6bef8672 100644 --- a/dbms/src/Functions/array/arrayIndex.h +++ b/dbms/src/Functions/array/arrayIndex.h @@ -751,7 +751,7 @@ private: Array arr = col_array->getValue(); const auto item_arg = block.getByPosition(arguments[1]).column.get(); - if (item_arg->isColumnConst()) + if (isColumnConst(*item_arg)) { typename IndexConv::ResultType current = 0; const auto & value = (*item_arg)[0]; @@ -848,7 +848,7 @@ private: if (item_arg.onlyNull()) ArrayIndexGenericNullImpl::vector(col_nested, col_array->getOffsets(), col_res->getData(), null_map_data); - else if (item_arg.isColumnConst()) + else if (isColumnConst(item_arg)) ArrayIndexGenericImpl::vector(col_nested, col_array->getOffsets(), static_cast(item_arg).getDataColumn(), col_res->getData(), /// TODO This is wrong. null_map_data, nullptr); @@ -907,22 +907,20 @@ public: /// (they are vectors of Fields, which may represent the NULL value), /// they do not require any preprocessing - /// Check if the 1st function argument is a non-constant array of nullable - /// values. - bool is_nullable; - const ColumnArray * col_array = checkAndGetColumn(block.getByPosition(arguments[0]).column.get()); + + const ColumnNullable * nullable = nullptr; if (col_array) - is_nullable = col_array->getData().isColumnNullable(); - else - is_nullable = false; + nullable = checkAndGetColumn(col_array->getData()); - /// Check nullability of the 2nd function argument. - bool is_arg_nullable = block.getByPosition(arguments[1]).column->isColumnNullable(); + auto & arg_column = block.getByPosition(arguments[1]).column; - if (!is_nullable && !is_arg_nullable) + const ColumnNullable * arg_nullable = nullptr; + arg_nullable = checkAndGetColumn(*arg_column); + + if (!nullable && !arg_nullable) { - /// Simple case: no nullable value is passed. + /// Simple case: no nullable values passeded. perform(block, arguments, result); } else @@ -955,10 +953,9 @@ public: } }; - if (is_nullable) + if (nullable) { - const auto & nullable_col = static_cast(col_array->getData()); - const auto & nested_col = nullable_col.getNestedColumnPtr(); + const auto & nested_col = nullable->getNestedColumnPtr(); auto & data = source_block.getByPosition(0); data.column = ColumnArray::create(nested_col, col_array->getOffsetsPtr()); @@ -967,7 +964,7 @@ public: *static_cast(*block.getByPosition(arguments[0]).type).getNestedType()).getNestedType()); auto & null_map = source_block.getByPosition(2); - null_map.column = nullable_col.getNullMapColumnPtr(); + null_map.column = nullable->getNullMapColumnPtr(); null_map.type = std::make_shared(); } else @@ -976,17 +973,14 @@ public: data = block.getByPosition(arguments[0]); } - if (is_arg_nullable) + if (arg_nullable) { - const auto & col = block.getByPosition(arguments[1]).column; - const auto & nullable_col = static_cast(*col); - auto & arg = source_block.getByPosition(1); - arg.column = nullable_col.getNestedColumnPtr(); + arg.column = arg_nullable->getNestedColumnPtr(); arg.type = static_cast(*block.getByPosition(arguments[1]).type).getNestedType(); auto & null_map = source_block.getByPosition(3); - null_map.column = nullable_col.getNullMapColumnPtr(); + null_map.column = arg_nullable->getNullMapColumnPtr(); null_map.type = std::make_shared(); } else diff --git a/dbms/src/Functions/array/arrayResize.cpp b/dbms/src/Functions/array/arrayResize.cpp index 935e2039fe3..d4f37823e0b 100644 --- a/dbms/src/Functions/array/arrayResize.cpp +++ b/dbms/src/Functions/array/arrayResize.cpp @@ -124,7 +124,7 @@ public: auto sink = GatherUtils::createArraySink(typeid_cast(*result_column), size); - if (size_column->isColumnConst()) + if (isColumnConst(*size_column)) GatherUtils::resizeConstantSize(*array_source, *value_source, *sink, size_column->getInt(0)); else GatherUtils::resizeDynamicSize(*array_source, *value_source, *sink, *size_column); diff --git a/dbms/src/Functions/array/arraySlice.cpp b/dbms/src/Functions/array/arraySlice.cpp index 08854ee1079..a7f7b0ce307 100644 --- a/dbms/src/Functions/array/arraySlice.cpp +++ b/dbms/src/Functions/array/arraySlice.cpp @@ -110,7 +110,7 @@ public: block.getByPosition(result).column = array_column; return; } - else if (length_column->isColumnConst()) + else if (isColumnConst(*length_column)) GatherUtils::sliceFromLeftConstantOffsetBounded(*source, *sink, 0, length_column->getInt(0)); else { @@ -118,7 +118,7 @@ public: GatherUtils::sliceDynamicOffsetBounded(*source, *sink, *const_offset_column, *length_column); } } - else if (offset_column->isColumnConst()) + else if (isColumnConst(*offset_column)) { ssize_t offset = offset_column->getUInt(0); @@ -129,7 +129,7 @@ public: else GatherUtils::sliceFromRightConstantOffsetUnbounded(*source, *sink, static_cast(-offset)); } - else if (length_column->isColumnConst()) + else if (isColumnConst(*length_column)) { ssize_t length = length_column->getInt(0); if (offset > 0) diff --git a/dbms/src/Functions/array/arrayUniq.cpp b/dbms/src/Functions/array/arrayUniq.cpp index 29106cf235f..abb5efeeed6 100644 --- a/dbms/src/Functions/array/arrayUniq.cpp +++ b/dbms/src/Functions/array/arrayUniq.cpp @@ -154,14 +154,12 @@ void FunctionArrayUniq::executeImpl(Block & block, const ColumnNumbers & argumen for (size_t i = 0; i < num_arguments; ++i) { - if (data_columns[i]->isColumnNullable()) + if (auto * nullable_col = checkAndGetColumn(*data_columns[i])) { - const auto & nullable_col = static_cast(*data_columns[i]); - if (num_arguments == 1) - data_columns[i] = &nullable_col.getNestedColumn(); + data_columns[i] = &nullable_col->getNestedColumn(); - null_map = &nullable_col.getNullMapData(); + null_map = &nullable_col->getNullMapData(); break; } } diff --git a/dbms/src/Functions/array/emptyArrayToSingle.cpp b/dbms/src/Functions/array/emptyArrayToSingle.cpp index ae073935c27..2a98faea32a 100644 --- a/dbms/src/Functions/array/emptyArrayToSingle.cpp +++ b/dbms/src/Functions/array/emptyArrayToSingle.cpp @@ -392,16 +392,15 @@ void FunctionEmptyArrayToSingle::executeImpl(Block & block, const ColumnNumbers const IColumn * inner_col; IColumn * inner_res_col; - bool nullable = src_data.isColumnNullable(); - if (nullable) + auto nullable_col = checkAndGetColumn(src_data); + if (nullable_col) { - auto nullable_col = static_cast(&src_data); inner_col = &nullable_col->getNestedColumn(); src_null_map = &nullable_col->getNullMapData(); - auto nullable_res_col = static_cast(&res_data); - inner_res_col = &nullable_res_col->getNestedColumn(); - res_null_map = &nullable_res_col->getNullMapData(); + auto & nullable_res_col = static_cast(res_data); + inner_res_col = &nullable_res_col.getNestedColumn(); + res_null_map = &nullable_res_col.getNullMapData(); } else { @@ -409,7 +408,7 @@ void FunctionEmptyArrayToSingle::executeImpl(Block & block, const ColumnNumbers inner_res_col = &res_data; } - if (nullable) + if (nullable_col) FunctionEmptyArrayToSingleImpl::executeDispatch(*inner_col, src_offsets, *inner_res_col, res_offsets, src_null_map, res_null_map); else FunctionEmptyArrayToSingleImpl::executeDispatch(*inner_col, src_offsets, *inner_res_col, res_offsets, src_null_map, res_null_map); diff --git a/dbms/src/Functions/assumeNotNull.cpp b/dbms/src/Functions/assumeNotNull.cpp index 509cc84969f..5439b4eb7a3 100644 --- a/dbms/src/Functions/assumeNotNull.cpp +++ b/dbms/src/Functions/assumeNotNull.cpp @@ -42,11 +42,8 @@ public: const ColumnPtr & col = block.getByPosition(arguments[0]).column; ColumnPtr & res_col = block.getByPosition(result).column; - if (col->isColumnNullable()) - { - const ColumnNullable & nullable_col = static_cast(*col); - res_col = nullable_col.getNestedColumnPtr(); - } + if (auto * nullable_col = checkAndGetColumn(*col)) + res_col = nullable_col->getNestedColumnPtr(); else res_col = col; } diff --git a/dbms/src/Functions/bar.cpp b/dbms/src/Functions/bar.cpp index 9121c479bf1..123ea38f1d6 100644 --- a/dbms/src/Functions/bar.cpp +++ b/dbms/src/Functions/bar.cpp @@ -108,7 +108,7 @@ private: { const auto & column = *block.getByPosition(arguments[argument_pos]).column; - if (!column.isColumnConst()) + if (!isColumnConst(column)) throw Exception( which_argument + String(" argument for function ") + getName() + " must be constant.", ErrorCodes::ILLEGAL_COLUMN); diff --git a/dbms/src/Functions/bitTest.cpp b/dbms/src/Functions/bitTest.cpp index 1818f7af479..ebb52a4dacf 100644 --- a/dbms/src/Functions/bitTest.cpp +++ b/dbms/src/Functions/bitTest.cpp @@ -1,5 +1,7 @@ #include #include +#include + namespace DB { @@ -10,7 +12,7 @@ struct BitTestImpl using ResultType = UInt8; template - static inline Result apply(A a, B b) + NO_SANITIZE_UNDEFINED static inline Result apply(A a, B b) { return (typename NumberTraits::ToInteger::Type(a) >> typename NumberTraits::ToInteger::Type(b)) & 1; } diff --git a/dbms/src/Functions/coalesce.cpp b/dbms/src/Functions/coalesce.cpp index cb65a019a31..7ef7eeadfdb 100644 --- a/dbms/src/Functions/coalesce.cpp +++ b/dbms/src/Functions/coalesce.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace DB @@ -150,8 +151,15 @@ public: ColumnPtr res = std::move(temp_block.getByPosition(result).column); /// if last argument is not nullable, result should be also not nullable - if (!block.getByPosition(multi_if_args.back()).column->isColumnNullable() && res->isColumnNullable()) - res = static_cast(*res).getNestedColumnPtr(); + if (!block.getByPosition(multi_if_args.back()).column->isNullable() && res->isNullable()) + { + if (auto * column_lc = checkAndGetColumn(*res)) + res = checkAndGetColumn(*column_lc->convertToFullColumn())->getNestedColumnPtr(); + else if (auto * column_const = checkAndGetColumn(*res)) + res = checkAndGetColumn(column_const->getDataColumn())->getNestedColumnPtr(); + else + res = checkAndGetColumn(*res)->getNestedColumnPtr(); + } block.getByPosition(result).column = std::move(res); } diff --git a/dbms/src/Functions/config_functions.h.in b/dbms/src/Functions/config_functions.h.in index a6b5e9790c0..7d395741b78 100644 --- a/dbms/src/Functions/config_functions.h.in +++ b/dbms/src/Functions/config_functions.h.in @@ -8,3 +8,4 @@ #cmakedefine01 USE_HYPERSCAN #cmakedefine01 USE_SIMDJSON #cmakedefine01 USE_RAPIDJSON +#cmakedefine01 USE_H3 diff --git a/dbms/src/Functions/geoToH3.cpp b/dbms/src/Functions/geoToH3.cpp new file mode 100644 index 00000000000..6d3a7197ee0 --- /dev/null +++ b/dbms/src/Functions/geoToH3.cpp @@ -0,0 +1,108 @@ +#include "config_functions.h" +#if USE_H3 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern "C" +{ +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" +#endif + +#include + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +} + +namespace DB +{ +namespace ErrorCodes +{ + extern const int ILLEGAL_COLUMN; +} + +/// Implements the function geoToH3 which takes 3 arguments (latitude, longitude and h3 resolution) +/// and returns h3 index of this point +class FunctionGeoToH3 : public IFunction +{ +public: + static constexpr auto name = "geoToH3"; + + static FunctionPtr create(const Context &) { return std::make_shared(); } + + std::string getName() const override { return name; } + + size_t getNumberOfArguments() const override { return 3; } + bool useDefaultImplementationForConstants() const override { return true; } + + DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override + { + auto arg = arguments[0].get(); + if (!WhichDataType(arg).isFloat64()) + throw Exception( + "Illegal type " + arg->getName() + " of argument " + std::to_string(1) + " of function " + getName() + ". Must be Float64", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + + arg = arguments[1].get(); + if (!WhichDataType(arg).isFloat64()) + throw Exception( + "Illegal type " + arg->getName() + " of argument " + std::to_string(2) + " of function " + getName() + ". Must be Float64", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + + arg = arguments[2].get(); + if (!WhichDataType(arg).isUInt8()) + throw Exception( + "Illegal type " + arg->getName() + " of argument " + std::to_string(3) + " of function " + getName() + ". Must be UInt8", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + + return std::make_shared(); + } + + void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override + { + const auto col_lon = block.getByPosition(arguments[0]).column.get(); + const auto col_lat = block.getByPosition(arguments[1]).column.get(); + const auto col_res = block.getByPosition(arguments[2]).column.get(); + + auto dst = ColumnVector::create(); + auto & dst_data = dst->getData(); + dst_data.resize(input_rows_count); + + for (const auto row : ext::range(0, input_rows_count)) + { + const double lon = col_lon->getFloat64(row); + const double lat = col_lat->getFloat64(row); + const UInt8 res = col_res->getUInt(row); + + GeoCoord coord; + coord.lon = H3_EXPORT(degsToRads)(lon); + coord.lat = H3_EXPORT(degsToRads)(lat); + + H3Index hindex = H3_EXPORT(geoToH3)(&coord, res); + + dst_data[row] = hindex; + } + + block.getByPosition(result).column = std::move(dst); + } +}; + + +void registerFunctionGeoToH3(FunctionFactory & factory) +{ + factory.registerFunction(); +} + +} +#endif diff --git a/dbms/src/Functions/geohashDecode.cpp b/dbms/src/Functions/geohashDecode.cpp new file mode 100644 index 00000000000..9774ecdee40 --- /dev/null +++ b/dbms/src/Functions/geohashDecode.cpp @@ -0,0 +1,99 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int ILLEGAL_COLUMN; +} + + +// geohashDecode(string) => (lon float64, lat float64) +class FunctionGeohashDecode : public IFunction +{ +public: + static constexpr auto name = "geohashDecode"; + static FunctionPtr create(const Context &) { return std::make_shared(); } + + String getName() const override + { + return name; + } + + size_t getNumberOfArguments() const override { return 1; } + bool useDefaultImplementationForConstants() const override { return true; } + + DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override + { + validateArgumentType(*this, arguments, 0, isStringOrFixedString, "string or fixed string"); + + return std::make_shared( + DataTypes{std::make_shared(), std::make_shared()}, + Strings{"longitude", "latitude"}); + } + + template + bool tryExecute(const IColumn * encoded_column, ColumnPtr & result_column) + { + const auto * encoded = checkAndGetColumn(encoded_column); + if (!encoded) + return false; + + const size_t count = encoded->size(); + + auto latitude = ColumnFloat64::create(count); + auto longitude = ColumnFloat64::create(count); + + ColumnFloat64::Container & lon_data = longitude->getData(); + ColumnFloat64::Container & lat_data = latitude->getData(); + + for (size_t i = 0; i < count; ++i) + { + StringRef encoded_string = encoded->getDataAt(i); + GeoUtils::geohashDecode(encoded_string.data, encoded_string.size, &lon_data[i], &lat_data[i]); + } + + MutableColumns result; + result.emplace_back(std::move(longitude)); + result.emplace_back(std::move(latitude)); + result_column = ColumnTuple::create(std::move(result)); + + return true; + } + + void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override + { + const IColumn * encoded = block.getByPosition(arguments[0]).column.get(); + ColumnPtr & res_column = block.getByPosition(result).column; + + if (tryExecute(encoded, res_column) || + tryExecute(encoded, res_column)) + return; + + throw Exception("Unsupported argument type:" + block.getByPosition(arguments[0]).column->getName() + + " of argument of function " + getName(), + ErrorCodes::ILLEGAL_COLUMN); + } +}; + + +void registerFunctionGeohashDecode(FunctionFactory & factory) +{ + factory.registerFunction(); +} + +} diff --git a/dbms/src/Functions/geohashEncode.cpp b/dbms/src/Functions/geohashEncode.cpp new file mode 100644 index 00000000000..9f4ccddd0f4 --- /dev/null +++ b/dbms/src/Functions/geohashEncode.cpp @@ -0,0 +1,136 @@ +#include +#include +#include + +#include +#include + +#include + +#define GEOHASH_MAX_TEXT_LENGTH 16 + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int LOGICAL_ERROR; + extern const int ILLEGAL_COLUMN; + extern const int TOO_MANY_ARGUMENTS_FOR_FUNCTION; +} + +// geohashEncode(lon float32/64, lat float32/64, length UInt8) => string +class FunctionGeohashEncode : public IFunction +{ +public: + static constexpr auto name = "geohashEncode"; + static FunctionPtr create(const Context &) { return std::make_shared(); } + + String getName() const override + { + return name; + } + + bool isVariadic() const override { return true; } + size_t getNumberOfArguments() const override { return 0; } + ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {2}; } + bool useDefaultImplementationForConstants() const override { return true; } + + DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override + { + validateArgumentType(*this, arguments, 0, isFloat, "float"); + validateArgumentType(*this, arguments, 1, isFloat, "float"); + if (arguments.size() == 3) + { + validateArgumentType(*this, arguments, 2, isInteger, "integer"); + } + if (arguments.size() > 3) + { + throw Exception("Too many arguments for function " + getName() + + " expected at most 3", + ErrorCodes::TOO_MANY_ARGUMENTS_FOR_FUNCTION); + } + + return std::make_shared(); + } + + template + bool tryExecute(const IColumn * lon_column, const IColumn * lat_column, UInt64 precision_value, ColumnPtr & result) + { + const ColumnVector * longitude = checkAndGetColumn>(lon_column); + const ColumnVector * latitude = checkAndGetColumn>(lat_column); + if (!latitude || !longitude) + return false; + + auto col_str = ColumnString::create(); + ColumnString::Chars & out_vec = col_str->getChars(); + ColumnString::Offsets & out_offsets = col_str->getOffsets(); + + const size_t size = lat_column->size(); + + out_offsets.resize(size); + out_vec.resize(size * (GEOHASH_MAX_TEXT_LENGTH + 1)); + + char * begin = reinterpret_cast(out_vec.data()); + char * pos = begin; + + for (size_t i = 0; i < size; ++i) + { + const Float64 longitude_value = longitude->getElement(i); + const Float64 latitude_value = latitude->getElement(i); + + const size_t encoded_size = GeoUtils::geohashEncode(longitude_value, latitude_value, precision_value, pos); + + pos += encoded_size; + *pos = '\0'; + out_offsets[i] = ++pos - begin; + } + out_vec.resize(pos - begin); + + if (!out_offsets.empty() && out_offsets.back() != out_vec.size()) + throw Exception("Column size mismatch (internal logical error)", ErrorCodes::LOGICAL_ERROR); + + result = std::move(col_str); + + return true; + + } + + void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override + { + const IColumn * longitude = block.getByPosition(arguments[0]).column.get(); + const IColumn * latitude = block.getByPosition(arguments[1]).column.get(); + + const UInt64 precision_value = std::min(GEOHASH_MAX_TEXT_LENGTH, + arguments.size() == 3 ? block.getByPosition(arguments[2]).column->get64(0) : GEOHASH_MAX_TEXT_LENGTH); + + ColumnPtr & res_column = block.getByPosition(result).column; + + if (tryExecute(longitude, latitude, precision_value, res_column) || + tryExecute(longitude, latitude, precision_value, res_column) || + tryExecute(longitude, latitude, precision_value, res_column) || + tryExecute(longitude, latitude, precision_value, res_column)) + return; + + std::string arguments_description; + for (size_t i = 0; i < arguments.size(); ++i) + { + if (i != 0) + arguments_description += ", "; + arguments_description += block.getByPosition(arguments[i]).column->getName(); + } + + throw Exception("Unsupported argument types: " + arguments_description + + + " for function " + getName(), + ErrorCodes::ILLEGAL_COLUMN); + } +}; + + +void registerFunctionGeohashEncode(FunctionFactory & factory) +{ + factory.registerFunction(); +} + +} diff --git a/dbms/src/Functions/greatCircleDistance.cpp b/dbms/src/Functions/greatCircleDistance.cpp new file mode 100644 index 00000000000..593334c6cfb --- /dev/null +++ b/dbms/src/Functions/greatCircleDistance.cpp @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEGREES_IN_RADIANS (M_PI / 180.0) +#define EARTH_RADIUS_IN_METERS 6372797.560856 + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int ARGUMENT_OUT_OF_BOUND; + extern const int ILLEGAL_COLUMN; + extern const int LOGICAL_ERROR; +} + +static inline Float64 degToRad(Float64 angle) { return angle * DEGREES_IN_RADIANS; } + +/** + * The function calculates distance in meters between two points on Earth specified by longitude and latitude in degrees. + * The function uses great circle distance formula https://en.wikipedia.org/wiki/Great-circle_distance. + * Throws exception when one or several input values are not within reasonable bounds. + * Latitude must be in [-90, 90], longitude must be [-180, 180] + * + */ +class FunctionGreatCircleDistance : public IFunction +{ +public: + + static constexpr auto name = "greatCircleDistance"; + static FunctionPtr create(const Context &) { return std::make_shared(); } + +private: + + enum class instr_type : uint8_t + { + get_float_64, + get_const_float_64 + }; + + using instr_t = std::pair; + using instrs_t = std::array; + + String getName() const override { return name; } + + size_t getNumberOfArguments() const override { return 4; } + + DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override + { + for (const auto arg_idx : ext::range(0, arguments.size())) + { + const auto arg = arguments[arg_idx].get(); + if (!WhichDataType(arg).isFloat64()) + throw Exception( + "Illegal type " + arg->getName() + " of argument " + std::to_string(arg_idx + 1) + " of function " + getName() + ". Must be Float64", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + } + + return std::make_shared(); + } + + instrs_t getInstructions(const Block & block, const ColumnNumbers & arguments, bool & out_const) + { + instrs_t result; + out_const = true; + + for (const auto arg_idx : ext::range(0, arguments.size())) + { + const auto column = block.getByPosition(arguments[arg_idx]).column.get(); + + if (const auto col = checkAndGetColumn>(column)) + { + out_const = false; + result[arg_idx] = instr_t{instr_type::get_float_64, col}; + } + else if (const auto col_const = checkAndGetColumnConst>(column)) + { + result[arg_idx] = instr_t{instr_type::get_const_float_64, col_const}; + } + else + throw Exception("Illegal column " + column->getName() + " of argument of function " + getName(), + ErrorCodes::ILLEGAL_COLUMN); + } + + return result; + } + + /// https://en.wikipedia.org/wiki/Great-circle_distance + Float64 greatCircleDistance(Float64 lon1Deg, Float64 lat1Deg, Float64 lon2Deg, Float64 lat2Deg) + { + if (lon1Deg < -180 || lon1Deg > 180 || + lon2Deg < -180 || lon2Deg > 180 || + lat1Deg < -90 || lat1Deg > 90 || + lat2Deg < -90 || lat2Deg > 90) + { + throw Exception("Arguments values out of bounds for function " + getName(), ErrorCodes::ARGUMENT_OUT_OF_BOUND); + } + + Float64 lon1Rad = degToRad(lon1Deg); + Float64 lat1Rad = degToRad(lat1Deg); + Float64 lon2Rad = degToRad(lon2Deg); + Float64 lat2Rad = degToRad(lat2Deg); + Float64 u = sin((lat2Rad - lat1Rad) / 2); + Float64 v = sin((lon2Rad - lon1Rad) / 2); + return 2.0 * EARTH_RADIUS_IN_METERS * asin(sqrt(u * u + cos(lat1Rad) * cos(lat2Rad) * v * v)); + } + + + void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override + { + const auto size = input_rows_count; + + bool result_is_const{}; + auto instrs = getInstructions(block, arguments, result_is_const); + + if (result_is_const) + { + const auto & colLon1 = static_cast(block.getByPosition(arguments[0]).column.get())->getValue(); + const auto & colLat1 = static_cast(block.getByPosition(arguments[1]).column.get())->getValue(); + const auto & colLon2 = static_cast(block.getByPosition(arguments[2]).column.get())->getValue(); + const auto & colLat2 = static_cast(block.getByPosition(arguments[3]).column.get())->getValue(); + + Float64 res = greatCircleDistance(colLon1, colLat1, colLon2, colLat2); + block.getByPosition(result).column = block.getByPosition(result).type->createColumnConst(size, res); + } + else + { + auto dst = ColumnVector::create(); + auto & dst_data = dst->getData(); + dst_data.resize(size); + Float64 vals[instrs.size()]; + for (const auto row : ext::range(0, size)) + { + for (const auto idx : ext::range(0, instrs.size())) + { + if (instr_type::get_float_64 == instrs[idx].first) + vals[idx] = static_cast *>(instrs[idx].second)->getData()[row]; + else if (instr_type::get_const_float_64 == instrs[idx].first) + vals[idx] = static_cast(instrs[idx].second)->getValue(); + else + throw Exception{"Unknown instruction type in implementation of greatCircleDistance function", ErrorCodes::LOGICAL_ERROR}; + } + dst_data[row] = greatCircleDistance(vals[0], vals[1], vals[2], vals[3]); + } + block.getByPosition(result).column = std::move(dst); + } + } +}; + + +void registerFunctionGreatCircleDistance(FunctionFactory & factory) +{ + factory.registerFunction(); +} + +} + diff --git a/dbms/src/Functions/if.cpp b/dbms/src/Functions/if.cpp index ff034848460..6676ad87d75 100644 --- a/dbms/src/Functions/if.cpp +++ b/dbms/src/Functions/if.cpp @@ -605,8 +605,8 @@ private: MutableColumnPtr result_column = common_type->createColumn(); result_column->reserve(input_rows_count); - bool then_is_const = col_then->isColumnConst(); - bool else_is_const = col_else->isColumnConst(); + bool then_is_const = isColumnConst(*col_then); + bool else_is_const = isColumnConst(*col_else); const auto & cond_array = cond_col->getData(); @@ -660,7 +660,6 @@ private: { const ColumnWithTypeAndName & arg_cond = block.getByPosition(arguments[0]); bool cond_is_null = arg_cond.column->onlyNull(); - bool cond_is_nullable = arg_cond.column->isColumnNullable(); if (cond_is_null) { @@ -668,11 +667,11 @@ private: return true; } - if (cond_is_nullable) + if (auto * nullable = checkAndGetColumn(*arg_cond.column)) { Block temporary_block { - { static_cast(*arg_cond.column).getNestedColumnPtr(), removeNullable(arg_cond.type), arg_cond.name }, + { nullable->getNestedColumnPtr(), removeNullable(arg_cond.type), arg_cond.name }, block.getByPosition(arguments[1]), block.getByPosition(arguments[2]), block.getByPosition(result) @@ -694,7 +693,7 @@ private: static ColumnPtr makeNullableColumnIfNot(const ColumnPtr & column) { - if (column->isColumnNullable()) + if (isColumnNullable(*column)) return column; return ColumnNullable::create( @@ -703,8 +702,8 @@ private: static ColumnPtr getNestedColumn(const ColumnPtr & column) { - if (column->isColumnNullable()) - return static_cast(*column).getNestedColumnPtr(); + if (auto * nullable = checkAndGetColumn(*column)) + return nullable->getNestedColumnPtr(); return column; } @@ -715,8 +714,8 @@ private: const ColumnWithTypeAndName & arg_then = block.getByPosition(arguments[1]); const ColumnWithTypeAndName & arg_else = block.getByPosition(arguments[2]); - bool then_is_nullable = typeid_cast(arg_then.column.get()); - bool else_is_nullable = typeid_cast(arg_else.column.get()); + auto * then_is_nullable = checkAndGetColumn(*arg_then.column); + auto * else_is_nullable = checkAndGetColumn(*arg_else.column); if (!then_is_nullable && !else_is_nullable) return false; @@ -731,14 +730,14 @@ private: arg_cond, { then_is_nullable - ? static_cast(arg_then.column.get())->getNullMapColumnPtr() + ? then_is_nullable->getNullMapColumnPtr() : DataTypeUInt8().createColumnConstWithDefaultValue(input_rows_count), std::make_shared(), "" }, { else_is_nullable - ? static_cast(arg_else.column.get())->getNullMapColumnPtr() + ? else_is_nullable->getNullMapColumnPtr() : DataTypeUInt8().createColumnConstWithDefaultValue(input_rows_count), std::make_shared(), "" @@ -814,7 +813,7 @@ private: { if (cond_col) { - if (arg_else.column->isColumnNullable()) + if (isColumnNullable(*arg_else.column)) { auto arg_else_column = arg_else.column; auto result_column = (*std::move(arg_else_column)).mutate(); @@ -856,7 +855,7 @@ private: for (size_t i = 0; i < size; ++i) negated_null_map_data[i] = !null_map_data[i]; - if (arg_then.column->isColumnNullable()) + if (isColumnNullable(*arg_then.column)) { auto arg_then_column = arg_then.column; auto result_column = (*std::move(arg_then_column)).mutate(); diff --git a/dbms/src/Functions/isNotNull.cpp b/dbms/src/Functions/isNotNull.cpp index 019654053da..546bf4a160a 100644 --- a/dbms/src/Functions/isNotNull.cpp +++ b/dbms/src/Functions/isNotNull.cpp @@ -38,11 +38,11 @@ public: void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override { const ColumnWithTypeAndName & elem = block.getByPosition(arguments[0]); - if (elem.column->isColumnNullable()) + if (auto * nullable = checkAndGetColumn(*elem.column)) { /// Return the negated null map. auto res_column = ColumnUInt8::create(input_rows_count); - const auto & src_data = static_cast(*elem.column).getNullMapData(); + const auto & src_data = nullable->getNullMapData(); auto & res_data = static_cast(*res_column).getData(); for (size_t i = 0; i < input_rows_count; ++i) diff --git a/dbms/src/Functions/isNull.cpp b/dbms/src/Functions/isNull.cpp index 9feb8a8afae..cc68753ea27 100644 --- a/dbms/src/Functions/isNull.cpp +++ b/dbms/src/Functions/isNull.cpp @@ -38,10 +38,10 @@ public: void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t) override { const ColumnWithTypeAndName & elem = block.getByPosition(arguments[0]); - if (elem.column->isColumnNullable()) + if (auto * nullable = checkAndGetColumn(*elem.column)) { /// Merely return the embedded null map. - block.getByPosition(result).column = static_cast(*elem.column).getNullMapColumnPtr(); + block.getByPosition(result).column = nullable->getNullMapColumnPtr(); } else { diff --git a/dbms/src/Functions/isValidUTF8.cpp b/dbms/src/Functions/isValidUTF8.cpp index 09b7b81030e..ff3c4466115 100644 --- a/dbms/src/Functions/isValidUTF8.cpp +++ b/dbms/src/Functions/isValidUTF8.cpp @@ -309,7 +309,7 @@ SOFTWARE. res[i] = isValidUTF8(data.data() + i * n, n); } - static void array(const ColumnString::Offsets &, PaddedPODArray &) + [[noreturn]] static void array(const ColumnString::Offsets &, PaddedPODArray &) { throw Exception("Cannot apply function isValidUTF8 to Array argument", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } diff --git a/dbms/src/Functions/lengthUTF8.cpp b/dbms/src/Functions/lengthUTF8.cpp index ba2214fc9d7..2549e32b8f7 100644 --- a/dbms/src/Functions/lengthUTF8.cpp +++ b/dbms/src/Functions/lengthUTF8.cpp @@ -48,7 +48,7 @@ struct LengthUTF8Impl } } - static void array(const ColumnString::Offsets &, PaddedPODArray &) + [[noreturn]] static void array(const ColumnString::Offsets &, PaddedPODArray &) { throw Exception("Cannot apply function lengthUTF8 to Array argument", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } diff --git a/dbms/src/Functions/multiIf.cpp b/dbms/src/Functions/multiIf.cpp index f5b27e798b3..7ee5f1c5e67 100644 --- a/dbms/src/Functions/multiIf.cpp +++ b/dbms/src/Functions/multiIf.cpp @@ -141,7 +141,7 @@ public: if (cond_col.column->onlyNull()) continue; - if (cond_col.column->isColumnConst()) + if (isColumnConst(*cond_col.column)) { Field value = typeid_cast(*cond_col.column).getField(); if (value.isNull()) @@ -152,7 +152,7 @@ public: } else { - if (cond_col.column->isColumnNullable()) + if (isColumnNullable(*cond_col.column)) instruction.condition_is_nullable = true; instruction.condition = cond_col.column.get(); @@ -171,7 +171,7 @@ public: instruction.source = converted_columns_holder.back().get(); } - if (instruction.source && instruction.source->isColumnConst()) + if (instruction.source && isColumnConst(*instruction.source)) instruction.source_is_constant = true; instructions.emplace_back(std::move(instruction)); diff --git a/dbms/src/Functions/FunctionsGeo.h b/dbms/src/Functions/pointInEllipses.cpp similarity index 54% rename from dbms/src/Functions/FunctionsGeo.h rename to dbms/src/Functions/pointInEllipses.cpp index 1f351633dd7..2958d6171f1 100644 --- a/dbms/src/Functions/FunctionsGeo.h +++ b/dbms/src/Functions/pointInEllipses.cpp @@ -1,17 +1,11 @@ -#pragma once - #include #include #include #include #include #include +#include #include -#include -#include - -#define DEGREES_IN_RADIANS (M_PI / 180.0) -#define EARTH_RADIUS_IN_METERS 6372797.560856 namespace DB @@ -19,148 +13,11 @@ namespace DB namespace ErrorCodes { - extern const int ARGUMENT_OUT_OF_BOUND; extern const int TOO_MANY_ARGUMENTS_FOR_FUNCTION; extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; extern const int ILLEGAL_COLUMN; - extern const int LOGICAL_ERROR; } -static inline Float64 degToRad(Float64 angle) { return angle * DEGREES_IN_RADIANS; } -static inline Float64 radToDeg(Float64 angle) { return angle / DEGREES_IN_RADIANS; } - -/** - * The function calculates distance in meters between two points on Earth specified by longitude and latitude in degrees. - * The function uses great circle distance formula https://en.wikipedia.org/wiki/Great-circle_distance. - * Throws exception when one or several input values are not within reasonable bounds. - * Latitude must be in [-90, 90], longitude must be [-180, 180] - * - */ -class FunctionGreatCircleDistance : public IFunction -{ -public: - - static constexpr auto name = "greatCircleDistance"; - static FunctionPtr create(const Context &) { return std::make_shared(); } - -private: - - enum class instr_type : uint8_t - { - get_float_64, - get_const_float_64 - }; - - using instr_t = std::pair; - using instrs_t = std::array; - - String getName() const override { return name; } - - size_t getNumberOfArguments() const override { return 4; } - - DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override - { - for (const auto arg_idx : ext::range(0, arguments.size())) - { - const auto arg = arguments[arg_idx].get(); - if (!WhichDataType(arg).isFloat64()) - throw Exception( - "Illegal type " + arg->getName() + " of argument " + std::to_string(arg_idx + 1) + " of function " + getName() + ". Must be Float64", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); - } - - return std::make_shared(); - } - - instrs_t getInstructions(const Block & block, const ColumnNumbers & arguments, bool & out_const) - { - instrs_t result; - out_const = true; - - for (const auto arg_idx : ext::range(0, arguments.size())) - { - const auto column = block.getByPosition(arguments[arg_idx]).column.get(); - - if (const auto col = checkAndGetColumn>(column)) - { - out_const = false; - result[arg_idx] = instr_t{instr_type::get_float_64, col}; - } - else if (const auto col_const = checkAndGetColumnConst>(column)) - { - result[arg_idx] = instr_t{instr_type::get_const_float_64, col_const}; - } - else - throw Exception("Illegal column " + column->getName() + " of argument of function " + getName(), - ErrorCodes::ILLEGAL_COLUMN); - } - - return result; - } - - /// https://en.wikipedia.org/wiki/Great-circle_distance - Float64 greatCircleDistance(Float64 lon1Deg, Float64 lat1Deg, Float64 lon2Deg, Float64 lat2Deg) - { - if (lon1Deg < -180 || lon1Deg > 180 || - lon2Deg < -180 || lon2Deg > 180 || - lat1Deg < -90 || lat1Deg > 90 || - lat2Deg < -90 || lat2Deg > 90) - { - throw Exception("Arguments values out of bounds for function " + getName(), ErrorCodes::ARGUMENT_OUT_OF_BOUND); - } - - Float64 lon1Rad = degToRad(lon1Deg); - Float64 lat1Rad = degToRad(lat1Deg); - Float64 lon2Rad = degToRad(lon2Deg); - Float64 lat2Rad = degToRad(lat2Deg); - Float64 u = sin((lat2Rad - lat1Rad) / 2); - Float64 v = sin((lon2Rad - lon1Rad) / 2); - return 2.0 * EARTH_RADIUS_IN_METERS * asin(sqrt(u * u + cos(lat1Rad) * cos(lat2Rad) * v * v)); - } - - - void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override - { - const auto size = input_rows_count; - - bool result_is_const{}; - auto instrs = getInstructions(block, arguments, result_is_const); - - if (result_is_const) - { - const auto & colLon1 = static_cast(block.getByPosition(arguments[0]).column.get())->getValue(); - const auto & colLat1 = static_cast(block.getByPosition(arguments[1]).column.get())->getValue(); - const auto & colLon2 = static_cast(block.getByPosition(arguments[2]).column.get())->getValue(); - const auto & colLat2 = static_cast(block.getByPosition(arguments[3]).column.get())->getValue(); - - Float64 res = greatCircleDistance(colLon1, colLat1, colLon2, colLat2); - block.getByPosition(result).column = block.getByPosition(result).type->createColumnConst(size, res); - } - else - { - auto dst = ColumnVector::create(); - auto & dst_data = dst->getData(); - dst_data.resize(size); - Float64 vals[instrs.size()]; - for (const auto row : ext::range(0, size)) - { - for (const auto idx : ext::range(0, instrs.size())) - { - if (instr_type::get_float_64 == instrs[idx].first) - vals[idx] = static_cast *>(instrs[idx].second)->getData()[row]; - else if (instr_type::get_const_float_64 == instrs[idx].first) - vals[idx] = static_cast(instrs[idx].second)->getValue(); - else - throw Exception{"Unknown instruction type in implementation of greatCircleDistance function", ErrorCodes::LOGICAL_ERROR}; - } - dst_data[row] = greatCircleDistance(vals[0], vals[1], vals[2], vals[3]); - } - block.getByPosition(result).column = std::move(dst); - } - } -}; - - /** * The function checks if a point is in one of ellipses in set. * The number of arguments must be 2 + 4*N where N is the number of ellipses. @@ -177,7 +34,6 @@ private: class FunctionPointInEllipses : public IFunction { public: - static constexpr auto name = "pointInEllipses"; static FunctionPtr create(const Context &) { return std::make_shared(); } @@ -330,6 +186,10 @@ private: } }; + +void registerFunctionPointInEllipses(FunctionFactory & factory) +{ + factory.registerFunction(); } -#undef DEGREES_IN_RADIANS +} diff --git a/dbms/src/Functions/FunctionsGeo.cpp b/dbms/src/Functions/pointInPolygon.cpp similarity index 55% rename from dbms/src/Functions/FunctionsGeo.cpp rename to dbms/src/Functions/pointInPolygon.cpp index 05ed8db2969..fc94be6c343 100644 --- a/dbms/src/Functions/FunctionsGeo.cpp +++ b/dbms/src/Functions/pointInPolygon.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -16,6 +15,7 @@ #include #include #include +#include #include #include @@ -37,6 +37,7 @@ namespace ErrorCodes extern const int TOO_FEW_ARGUMENTS_FOR_FUNCTION; extern const int BAD_ARGUMENTS; extern const int ILLEGAL_TYPE_OF_ARGUMENT; + extern const int ILLEGAL_COLUMN; } namespace FunctionPointInPolygonDetail @@ -251,185 +252,6 @@ private: }; -const size_t GEOHASH_MAX_TEXT_LENGTH = 16; - -// geohashEncode(lon float32/64, lat float32/64, length UInt8) => string -class FunctionGeohashEncode : public IFunction -{ -public: - static constexpr auto name = "geohashEncode"; - static FunctionPtr create(const Context &) { return std::make_shared(); } - - String getName() const override - { - return name; - } - - bool isVariadic() const override { return true; } - size_t getNumberOfArguments() const override { return 0; } - ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {2}; } - bool useDefaultImplementationForConstants() const override { return true; } - - DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override - { - validateArgumentType(*this, arguments, 0, isFloat, "float"); - validateArgumentType(*this, arguments, 1, isFloat, "float"); - if (arguments.size() == 3) - { - validateArgumentType(*this, arguments, 2, isInteger, "integer"); - } - if (arguments.size() > 3) - { - throw Exception("Too many arguments for function " + getName() + - " expected at most 3", - ErrorCodes::TOO_MANY_ARGUMENTS_FOR_FUNCTION); - } - - return std::make_shared(); - } - - template - bool tryExecute(const IColumn * lon_column, const IColumn * lat_column, UInt64 precision_value, ColumnPtr & result) - { - const ColumnVector * longitude = checkAndGetColumn>(lon_column); - const ColumnVector * latitude = checkAndGetColumn>(lat_column); - if (!latitude || !longitude) - return false; - - auto col_str = ColumnString::create(); - ColumnString::Chars & out_vec = col_str->getChars(); - ColumnString::Offsets & out_offsets = col_str->getOffsets(); - - const size_t size = lat_column->size(); - - out_offsets.resize(size); - out_vec.resize(size * (GEOHASH_MAX_TEXT_LENGTH + 1)); - - char * begin = reinterpret_cast(out_vec.data()); - char * pos = begin; - - for (size_t i = 0; i < size; ++i) - { - const Float64 longitude_value = longitude->getElement(i); - const Float64 latitude_value = latitude->getElement(i); - - const size_t encoded_size = GeoUtils::geohashEncode(longitude_value, latitude_value, precision_value, pos); - - pos += encoded_size; - *pos = '\0'; - out_offsets[i] = ++pos - begin; - } - out_vec.resize(pos - begin); - - if (!out_offsets.empty() && out_offsets.back() != out_vec.size()) - throw Exception("Column size mismatch (internal logical error)", ErrorCodes::LOGICAL_ERROR); - - result = std::move(col_str); - - return true; - - } - - void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override - { - const IColumn * longitude = block.getByPosition(arguments[0]).column.get(); - const IColumn * latitude = block.getByPosition(arguments[1]).column.get(); - - const UInt64 precision_value = std::min(GEOHASH_MAX_TEXT_LENGTH, - arguments.size() == 3 ? block.getByPosition(arguments[2]).column->get64(0) : GEOHASH_MAX_TEXT_LENGTH); - - ColumnPtr & res_column = block.getByPosition(result).column; - - if (tryExecute(longitude, latitude, precision_value, res_column) || - tryExecute(longitude, latitude, precision_value, res_column) || - tryExecute(longitude, latitude, precision_value, res_column) || - tryExecute(longitude, latitude, precision_value, res_column)) - return; - - const char sep[] = ", "; - std::string arguments_description = ""; - for (size_t i = 0; i < arguments.size(); ++i) - { - arguments_description += block.getByPosition(arguments[i]).column->getName() + sep; - } - if (arguments_description.size() > sizeof(sep)) - { - arguments_description.erase(arguments_description.size() - sizeof(sep) - 1); - } - - throw Exception("Unsupported argument types: " + arguments_description + - + " for function " + getName(), - ErrorCodes::ILLEGAL_COLUMN); - } -}; - -// geohashDecode(string) => (lon float64, lat float64) -class FunctionGeohashDecode : public IFunction -{ -public: - static constexpr auto name = "geohashDecode"; - static FunctionPtr create(const Context &) { return std::make_shared(); } - - String getName() const override - { - return name; - } - - size_t getNumberOfArguments() const override { return 1; } - bool useDefaultImplementationForConstants() const override { return true; } - - DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override - { - validateArgumentType(*this, arguments, 0, isStringOrFixedString, "string or fixed string"); - - return std::make_shared( - DataTypes{std::make_shared(), std::make_shared()}, - Strings{"longitude", "latitude"}); - } - - template - bool tryExecute(const IColumn * encoded_column, ColumnPtr & result_column) - { - const auto * encoded = checkAndGetColumn(encoded_column); - if (!encoded) - return false; - - const size_t count = encoded->size(); - - auto latitude = ColumnFloat64::create(count); - auto longitude = ColumnFloat64::create(count); - - ColumnFloat64::Container & lon_data = longitude->getData(); - ColumnFloat64::Container & lat_data = latitude->getData(); - - for (size_t i = 0; i < count; ++i) - { - StringRef encoded_string = encoded->getDataAt(i); - GeoUtils::geohashDecode(encoded_string.data, encoded_string.size, &lon_data[i], &lat_data[i]); - } - - MutableColumns result; - result.emplace_back(std::move(longitude)); - result.emplace_back(std::move(latitude)); - result_column = ColumnTuple::create(std::move(result)); - - return true; - } - - void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override - { - const IColumn * encoded = block.getByPosition(arguments[0]).column.get(); - ColumnPtr & res_column = block.getByPosition(result).column; - - if (tryExecute(encoded, res_column) || - tryExecute(encoded, res_column)) - return; - - throw Exception("Unsupported argument type:" + block.getByPosition(arguments[0]).column->getName() - + " of argument of function " + getName(), - ErrorCodes::ILLEGAL_COLUMN); - } -}; template using Point = boost::geometry::model::d2::point_xy; @@ -440,13 +262,9 @@ using PointInPolygonWithGrid = GeoUtils::PointInPolygonWithGrid; template <> const char * FunctionPointInPolygon::name = "pointInPolygon"; -void registerFunctionsGeo(FunctionFactory & factory) +void registerFunctionPointInPolygon(FunctionFactory & factory) { - factory.registerFunction(); - factory.registerFunction(); - factory.registerFunction>(); - factory.registerFunction(); - factory.registerFunction(); } + } diff --git a/dbms/src/Functions/registerFunctionsDateTime.cpp b/dbms/src/Functions/registerFunctionsDateTime.cpp index 9540edaa6e4..adb2b240c91 100644 --- a/dbms/src/Functions/registerFunctionsDateTime.cpp +++ b/dbms/src/Functions/registerFunctionsDateTime.cpp @@ -16,6 +16,7 @@ void registerFunctionToStartOfDay(FunctionFactory &); void registerFunctionToMonday(FunctionFactory &); void registerFunctionToISOWeek(FunctionFactory &); void registerFunctionToISOYear(FunctionFactory &); +void registerFunctionToCustomWeek(FunctionFactory &); void registerFunctionToStartOfMonth(FunctionFactory &); void registerFunctionToStartOfQuarter(FunctionFactory &); void registerFunctionToStartOfYear(FunctionFactory &); @@ -79,6 +80,7 @@ void registerFunctionsDateTime(FunctionFactory & factory) registerFunctionToMonday(factory); registerFunctionToISOWeek(factory); registerFunctionToISOYear(factory); + registerFunctionToCustomWeek(factory); registerFunctionToStartOfMonth(factory); registerFunctionToStartOfQuarter(factory); registerFunctionToStartOfYear(factory); diff --git a/dbms/src/Functions/registerFunctionsGeo.cpp b/dbms/src/Functions/registerFunctionsGeo.cpp new file mode 100644 index 00000000000..0f436811874 --- /dev/null +++ b/dbms/src/Functions/registerFunctionsGeo.cpp @@ -0,0 +1,32 @@ +#include "config_functions.h" + +namespace DB +{ + +class FunctionFactory; + +void registerFunctionGreatCircleDistance(FunctionFactory & factory); +void registerFunctionPointInEllipses(FunctionFactory & factory); +void registerFunctionPointInPolygon(FunctionFactory & factory); +void registerFunctionGeohashEncode(FunctionFactory & factory); +void registerFunctionGeohashDecode(FunctionFactory & factory); + +#if USE_H3 +void registerFunctionGeoToH3(FunctionFactory &); +#endif + +void registerFunctionsGeo(FunctionFactory & factory) +{ + registerFunctionGreatCircleDistance(factory); + registerFunctionPointInEllipses(factory); + registerFunctionPointInPolygon(factory); + registerFunctionGeohashEncode(factory); + registerFunctionGeohashDecode(factory); + +#if USE_H3 + registerFunctionGeoToH3(factory); +#endif +} + +} + diff --git a/dbms/src/Functions/reverseUTF8.cpp b/dbms/src/Functions/reverseUTF8.cpp index 188b48bf7dc..261aa6935e2 100644 --- a/dbms/src/Functions/reverseUTF8.cpp +++ b/dbms/src/Functions/reverseUTF8.cpp @@ -61,7 +61,7 @@ struct ReverseUTF8Impl } } - static void vector_fixed(const ColumnString::Chars &, size_t, ColumnString::Chars &) + [[noreturn]] static void vector_fixed(const ColumnString::Chars &, size_t, ColumnString::Chars &) { throw Exception("Cannot apply function reverseUTF8 to fixed string.", ErrorCodes::ILLEGAL_COLUMN); } diff --git a/dbms/src/Functions/runningDifference.h b/dbms/src/Functions/runningDifference.h index a39f9effcf4..35987ca3aeb 100644 --- a/dbms/src/Functions/runningDifference.h +++ b/dbms/src/Functions/runningDifference.h @@ -167,7 +167,7 @@ public: const auto & res_type = block.getByPosition(result).type; /// When column is constant, its difference is zero. - if (src.column->isColumnConst()) + if (isColumnConst(*src.column)) { block.getByPosition(result).column = res_type->createColumnConstWithDefaultValue(input_rows_count); return; diff --git a/dbms/src/Functions/sleep.h b/dbms/src/Functions/sleep.h index c0b49f24ce6..9870e3430a6 100644 --- a/dbms/src/Functions/sleep.h +++ b/dbms/src/Functions/sleep.h @@ -69,7 +69,7 @@ public: { const IColumn * col = block.getByPosition(arguments[0]).column.get(); - if (!col->isColumnConst()) + if (!isColumnConst(*col)) throw Exception("The argument of function " + getName() + " must be constant.", ErrorCodes::ILLEGAL_COLUMN); Float64 seconds = applyVisitor(FieldVisitorConvertToNumber(), static_cast(*col).getField()); diff --git a/dbms/src/Functions/toCustomWeek.cpp b/dbms/src/Functions/toCustomWeek.cpp new file mode 100644 index 00000000000..5ba0b8e8b2a --- /dev/null +++ b/dbms/src/Functions/toCustomWeek.cpp @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include + + +namespace DB +{ +using FunctionToWeek = FunctionCustomWeekToSomething; +using FunctionToYearWeek = FunctionCustomWeekToSomething; +using FunctionToStartOfWeek = FunctionCustomWeekToSomething; + +void registerFunctionToCustomWeek(FunctionFactory & factory) +{ + factory.registerFunction(); + factory.registerFunction(); + factory.registerFunction(); + + /// Compatibility aliases for mysql. + factory.registerAlias("week", "toWeek", FunctionFactory::CaseInsensitive); + factory.registerAlias("yearweek", "toYearWeek", FunctionFactory::CaseInsensitive); +} + +} diff --git a/dbms/src/Functions/toValidUTF8.cpp b/dbms/src/Functions/toValidUTF8.cpp index a1dc78c7915..63e3bdab21d 100644 --- a/dbms/src/Functions/toValidUTF8.cpp +++ b/dbms/src/Functions/toValidUTF8.cpp @@ -124,7 +124,7 @@ struct ToValidUTF8Impl write_buffer.finish(); } - static void vector_fixed(const ColumnString::Chars &, size_t, ColumnString::Chars &) + [[noreturn]] static void vector_fixed(const ColumnString::Chars &, size_t, ColumnString::Chars &) { throw Exception("Column of type FixedString is not supported by toValidUTF8 function", ErrorCodes::ILLEGAL_COLUMN); } diff --git a/dbms/src/Functions/transform.cpp b/dbms/src/Functions/transform.cpp index 7f9a5d922a5..bac5adbb7b9 100644 --- a/dbms/src/Functions/transform.cpp +++ b/dbms/src/Functions/transform.cpp @@ -155,7 +155,7 @@ public: const auto in = block.getByPosition(arguments.front()).column.get(); - if (in->isColumnConst()) + if (isColumnConst(*in)) { executeConst(block, arguments, result, input_rows_count); return; @@ -228,7 +228,7 @@ private: executeImplNumToNum(in->getData(), out->getData()); } - else if (default_untyped->isColumnConst()) + else if (isColumnConst(*default_untyped)) { if (!executeNumToNumWithConstDefault(in, out_untyped) && !executeNumToNumWithConstDefault(in, out_untyped) @@ -281,7 +281,7 @@ private: throw Exception{"Illegal column " + in->getName() + " of elements of array of second argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN}; } - else if (default_untyped->isColumnConst()) + else if (isColumnConst(*default_untyped)) { if (!executeStringToNumWithConstDefault(in, out_untyped) && !executeStringToNumWithConstDefault(in, out_untyped) diff --git a/dbms/src/IO/DoubleConverter.h b/dbms/src/IO/DoubleConverter.h index e05226333dd..0c46024d65e 100644 --- a/dbms/src/IO/DoubleConverter.h +++ b/dbms/src/IO/DoubleConverter.h @@ -34,9 +34,11 @@ class DoubleConverter DoubleConverter() = default; public: - /** @todo Add commentary on how this constant is deduced. - * e.g. it's minus sign, integral zero, decimal point, up to 5 leading zeros and kBase10MaximalLength digits. */ - static constexpr auto MAX_REPRESENTATION_LENGTH = 26; + /// Sign (1 byte) + DigitsBeforePoint + point (1 byte) + DigitsAfterPoint + zero byte. + /// See comment to DoubleToStringConverter::ToFixed method for explanation. + static constexpr auto MAX_REPRESENTATION_LENGTH = + 1 + double_conversion::DoubleToStringConverter::kMaxFixedDigitsBeforePoint + + 1 + double_conversion::DoubleToStringConverter::kMaxFixedDigitsAfterPoint + 1; using BufferType = char[MAX_REPRESENTATION_LENGTH]; static const auto & instance() diff --git a/dbms/src/IO/HDFSCommon.cpp b/dbms/src/IO/HDFSCommon.cpp index 34cef18068f..4be67c7a0de 100644 --- a/dbms/src/IO/HDFSCommon.cpp +++ b/dbms/src/IO/HDFSCommon.cpp @@ -2,6 +2,7 @@ #if USE_HDFS #include + namespace DB { namespace ErrorCodes @@ -9,6 +10,7 @@ namespace ErrorCodes extern const int BAD_ARGUMENTS; extern const int NETWORK_ERROR; } + HDFSBuilderPtr createHDFSBuilder(const Poco::URI & uri) { auto & host = uri.getHost(); @@ -25,6 +27,18 @@ HDFSBuilderPtr createHDFSBuilder(const Poco::URI & uri) hdfsBuilderConfSetStr(builder.get(), "input.write.timeout", "60000"); // 1 min hdfsBuilderConfSetStr(builder.get(), "input.connect.timeout", "60000"); // 1 min + std::string user_info = uri.getUserInfo(); + if (!user_info.empty() && user_info.front() != ':') + { + std::string user; + size_t delim_pos = user_info.find(":"); + if (delim_pos != std::string::npos) + user = user_info.substr(0, delim_pos); + else + user = user_info; + + hdfsBuilderSetUserName(builder.get(), user.c_str()); + } hdfsBuilderSetNameNode(builder.get(), host.c_str()); hdfsBuilderSetNameNodePort(builder.get(), port); return builder; diff --git a/dbms/src/IO/ReadHelpers.h b/dbms/src/IO/ReadHelpers.h index a24c1b4546c..e1f0480a7a9 100644 --- a/dbms/src/IO/ReadHelpers.h +++ b/dbms/src/IO/ReadHelpers.h @@ -676,7 +676,7 @@ inline void readText(String & x, ReadBuffer & buf) { readEscapedString(x, buf); inline void readText(LocalDate & x, ReadBuffer & buf) { readDateText(x, buf); } inline void readText(LocalDateTime & x, ReadBuffer & buf) { readDateTimeText(x, buf); } inline void readText(UUID & x, ReadBuffer & buf) { readUUIDText(x, buf); } -inline void readText(UInt128 &, ReadBuffer &) +[[noreturn]] inline void readText(UInt128 &, ReadBuffer &) { /** Because UInt128 isn't a natural type, without arithmetic operator and only use as an intermediary type -for UUID- * it should never arrive here. But because we used the DataTypeNumber class we should have at least a definition of it. @@ -755,7 +755,7 @@ inline void readCSV(String & x, ReadBuffer & buf, const FormatSettings::CSV & se inline void readCSV(LocalDate & x, ReadBuffer & buf) { readCSVSimple(x, buf); } inline void readCSV(LocalDateTime & x, ReadBuffer & buf) { readCSVSimple(x, buf); } inline void readCSV(UUID & x, ReadBuffer & buf) { readCSVSimple(x, buf); } -inline void readCSV(UInt128 &, ReadBuffer &) +[[noreturn]] inline void readCSV(UInt128 &, ReadBuffer &) { /** Because UInt128 isn't a natural type, without arithmetic operator and only use as an intermediary type -for UUID- * it should never arrive here. But because we used the DataTypeNumber class we should have at least a definition of it. diff --git a/dbms/src/IO/WriteHelpers.h b/dbms/src/IO/WriteHelpers.h index b494f863421..073888c8712 100644 --- a/dbms/src/IO/WriteHelpers.h +++ b/dbms/src/IO/WriteHelpers.h @@ -830,7 +830,7 @@ inline void writeCSV(const String & x, WriteBuffer & buf) { writeCSVString<>(x, inline void writeCSV(const LocalDate & x, WriteBuffer & buf) { writeDoubleQuoted(x, buf); } inline void writeCSV(const LocalDateTime & x, WriteBuffer & buf) { writeDoubleQuoted(x, buf); } inline void writeCSV(const UUID & x, WriteBuffer & buf) { writeDoubleQuoted(x, buf); } -inline void writeCSV(const UInt128, WriteBuffer &) +[[noreturn]] inline void writeCSV(const UInt128, WriteBuffer &) { /** Because UInt128 isn't a natural type, without arithmetic operator and only use as an intermediary type -for UUID- * it should never arrive here. But because we used the DataTypeNumber class we should have at least a definition of it. diff --git a/dbms/src/IO/tests/CMakeLists.txt b/dbms/src/IO/tests/CMakeLists.txt index 127dc45d9bb..1c804b29c04 100644 --- a/dbms/src/IO/tests/CMakeLists.txt +++ b/dbms/src/IO/tests/CMakeLists.txt @@ -26,7 +26,7 @@ add_executable (read_escaped_string read_escaped_string.cpp) target_link_libraries (read_escaped_string PRIVATE clickhouse_common_io) add_executable (async_write async_write.cpp) -target_link_libraries (async_write PRIVATE clickhouse_compression clickhouse_common_io) +target_link_libraries (async_write PRIVATE dbms) add_executable (parse_int_perf parse_int_perf.cpp) target_link_libraries (parse_int_perf PRIVATE clickhouse_common_io) diff --git a/dbms/src/IO/tests/gtest_aio_seek_back_after_eof.cpp b/dbms/src/IO/tests/gtest_aio_seek_back_after_eof.cpp index 382182e8cbf..85643d2a78b 100644 --- a/dbms/src/IO/tests/gtest_aio_seek_back_after_eof.cpp +++ b/dbms/src/IO/tests/gtest_aio_seek_back_after_eof.cpp @@ -1,10 +1,5 @@ #if defined(__linux__) || defined(__FreeBSD__) -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" -#pragma clang diagnostic ignored "-Wundef" -#endif #include #include diff --git a/dbms/src/IO/tests/gtest_bit_io.cpp b/dbms/src/IO/tests/gtest_bit_io.cpp index abb5a53e346..85df2580783 100644 --- a/dbms/src/IO/tests/gtest_bit_io.cpp +++ b/dbms/src/IO/tests/gtest_bit_io.cpp @@ -16,12 +16,6 @@ #include #include -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" -#pragma clang diagnostic ignored "-Wundef" -#endif - #include using namespace DB; diff --git a/dbms/src/IO/tests/gtest_cascade_and_memory_write_buffer.cpp b/dbms/src/IO/tests/gtest_cascade_and_memory_write_buffer.cpp index ecf4054e122..aa95ab7cb58 100644 --- a/dbms/src/IO/tests/gtest_cascade_and_memory_write_buffer.cpp +++ b/dbms/src/IO/tests/gtest_cascade_and_memory_write_buffer.cpp @@ -1,8 +1,3 @@ -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ - #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" - #pragma clang diagnostic ignored "-Wundef" -#endif #include #include diff --git a/dbms/src/IO/tests/read_buffer_aio.cpp b/dbms/src/IO/tests/read_buffer_aio.cpp index 7ed07b0930c..81d04da79f2 100644 --- a/dbms/src/IO/tests/read_buffer_aio.cpp +++ b/dbms/src/IO/tests/read_buffer_aio.cpp @@ -18,7 +18,7 @@ void prepare2(std::string & filename, std::string & buf); void prepare3(std::string & filename, std::string & buf); void prepare4(std::string & filename, std::string & buf); std::string createTmpFile(); -void die(const std::string & msg); +[[noreturn]] void die(const std::string & msg); void runTest(unsigned int num, const std::function & func); bool test1(const std::string & filename); diff --git a/dbms/src/IO/tests/write_buffer_aio.cpp b/dbms/src/IO/tests/write_buffer_aio.cpp index df8dde6b190..4e76a91639c 100644 --- a/dbms/src/IO/tests/write_buffer_aio.cpp +++ b/dbms/src/IO/tests/write_buffer_aio.cpp @@ -14,7 +14,7 @@ namespace namespace fs = boost::filesystem; void run(); -void die(const std::string & msg); +[[noreturn]] void die(const std::string & msg); void runTest(unsigned int num, const std::function & func); std::string createTmpFile(); std::string generateString(size_t n); diff --git a/dbms/src/Interpreters/Aggregator.cpp b/dbms/src/Interpreters/Aggregator.cpp index 0c6477942dd..b3c0aa87f8a 100644 --- a/dbms/src/Interpreters/Aggregator.cpp +++ b/dbms/src/Interpreters/Aggregator.cpp @@ -1233,7 +1233,7 @@ Block Aggregator::prepareBlockAndFill( /// Change the size of the columns-constants in the block. size_t columns = header.columns(); for (size_t i = 0; i < columns; ++i) - if (res.getByPosition(i).column->isColumnConst()) + if (isColumnConst(*res.getByPosition(i).column)) res.getByPosition(i).column = res.getByPosition(i).column->cut(0, rows); return res; @@ -2053,7 +2053,6 @@ void Aggregator::mergeStream(const BlockInputStreamPtr & stream, AggregatedDataV * Then the calculations can be parallelized by buckets. * We decompose the blocks to the bucket numbers indicated in them. */ - using BucketToBlocks = std::map; BucketToBlocks bucket_to_blocks; /// Read all the data. @@ -2071,11 +2070,22 @@ void Aggregator::mergeStream(const BlockInputStreamPtr & stream, AggregatedDataV bucket_to_blocks[block.info.bucket_num].emplace_back(std::move(block)); } - LOG_TRACE(log, "Read " << total_input_blocks << " blocks of partially aggregated data, total " << total_input_rows << " rows."); + LOG_TRACE(log, "Read " << total_input_blocks << " blocks of partially aggregated data, total " << total_input_rows + << " rows."); + mergeBlocks(bucket_to_blocks, result, max_threads); +} + +void Aggregator::mergeBlocks(BucketToBlocks bucket_to_blocks, AggregatedDataVariants & result, size_t max_threads) +{ if (bucket_to_blocks.empty()) return; + UInt64 total_input_rows = 0; + for (auto & bucket : bucket_to_blocks) + for (auto & block : bucket.second) + total_input_rows += block.rows(); + /** `minus one` means the absence of information about the bucket * - in the case of single-level aggregation, as well as for blocks with "overflowing" values. * If there is at least one block with a bucket number greater or equal than zero, then there was a two-level aggregation. diff --git a/dbms/src/Interpreters/Aggregator.h b/dbms/src/Interpreters/Aggregator.h index 793179e060b..983f34c1933 100644 --- a/dbms/src/Interpreters/Aggregator.h +++ b/dbms/src/Interpreters/Aggregator.h @@ -307,8 +307,12 @@ struct AggregationMethodKeysFixed IColumn * observed_column; ColumnUInt8 * null_map; + bool column_nullable = false; + if constexpr (has_nullable_keys) + column_nullable = isColumnNullable(*key_columns[i]); + /// If we have a nullable column, get its nested column and its null map. - if (has_nullable_keys && key_columns[i]->isColumnNullable()) + if (column_nullable) { ColumnNullable & nullable_col = static_cast(*key_columns[i]); observed_column = &nullable_col.getNestedColumn(); @@ -320,8 +324,8 @@ struct AggregationMethodKeysFixed null_map = nullptr; } - bool is_null; - if (has_nullable_keys && key_columns[i]->isColumnNullable()) + bool is_null = false; + if (column_nullable) { /// The current column is nullable. Check if the value of the /// corresponding key is nullable. Update the null map accordingly. @@ -331,8 +335,6 @@ struct AggregationMethodKeysFixed null_map->insertValue(val); is_null = val == 1; } - else - is_null = false; if (has_nullable_keys && is_null) observed_column->insertDefault(); @@ -855,6 +857,10 @@ public: */ void mergeStream(const BlockInputStreamPtr & stream, AggregatedDataVariants & result, size_t max_threads); + using BucketToBlocks = std::map; + /// Merge partially aggregated blocks separated to buckets into one data structure. + void mergeBlocks(BucketToBlocks bucket_to_blocks, AggregatedDataVariants & result, size_t max_threads); + /// Merge several partially aggregated blocks into one. /// Precondition: for all blocks block.info.is_overflows flag must be the same. /// (either all blocks are from overflow data or none blocks are). diff --git a/dbms/src/Interpreters/BloomFilter.cpp b/dbms/src/Interpreters/BloomFilter.cpp index 765f1ea9478..d648fd114f4 100644 --- a/dbms/src/Interpreters/BloomFilter.cpp +++ b/dbms/src/Interpreters/BloomFilter.cpp @@ -1,5 +1,4 @@ #include - #include @@ -9,14 +8,13 @@ namespace DB static constexpr UInt64 SEED_GEN_A = 845897321; static constexpr UInt64 SEED_GEN_B = 217728422; - -StringBloomFilter::StringBloomFilter(size_t size_, size_t hashes_, size_t seed_) +BloomFilter::BloomFilter(size_t size_, size_t hashes_, size_t seed_) : size(size_), hashes(hashes_), seed(seed_), words((size + sizeof(UnderType) - 1) / sizeof(UnderType)), filter(words, 0) {} -StringBloomFilter::StringBloomFilter(const StringBloomFilter & bloom_filter) +BloomFilter::BloomFilter(const BloomFilter & bloom_filter) : size(bloom_filter.size), hashes(bloom_filter.hashes), seed(bloom_filter.seed), words(bloom_filter.words), filter(bloom_filter.filter) {} -bool StringBloomFilter::find(const char * data, size_t len) +bool BloomFilter::find(const char * data, size_t len) { size_t hash1 = CityHash_v1_0_2::CityHash64WithSeed(data, len, seed); size_t hash2 = CityHash_v1_0_2::CityHash64WithSeed(data, len, SEED_GEN_A * seed + SEED_GEN_B); @@ -30,7 +28,7 @@ bool StringBloomFilter::find(const char * data, size_t len) return true; } -void StringBloomFilter::add(const char * data, size_t len) +void BloomFilter::add(const char * data, size_t len) { size_t hash1 = CityHash_v1_0_2::CityHash64WithSeed(data, len, seed); size_t hash2 = CityHash_v1_0_2::CityHash64WithSeed(data, len, SEED_GEN_A * seed + SEED_GEN_B); @@ -42,12 +40,12 @@ void StringBloomFilter::add(const char * data, size_t len) } } -void StringBloomFilter::clear() +void BloomFilter::clear() { filter.assign(words, 0); } -bool StringBloomFilter::contains(const StringBloomFilter & bf) +bool BloomFilter::contains(const BloomFilter & bf) { for (size_t i = 0; i < words; ++i) { @@ -57,7 +55,7 @@ bool StringBloomFilter::contains(const StringBloomFilter & bf) return true; } -UInt64 StringBloomFilter::isEmpty() const +UInt64 BloomFilter::isEmpty() const { for (size_t i = 0; i < words; ++i) if (filter[i] != 0) @@ -65,7 +63,7 @@ UInt64 StringBloomFilter::isEmpty() const return true; } -bool operator== (const StringBloomFilter & a, const StringBloomFilter & b) +bool operator== (const BloomFilter & a, const BloomFilter & b) { for (size_t i = 0; i < a.words; ++i) if (a.filter[i] != b.filter[i]) @@ -73,4 +71,16 @@ bool operator== (const StringBloomFilter & a, const StringBloomFilter & b) return true; } +void BloomFilter::addHashWithSeed(const UInt64 & hash, const UInt64 & hash_seed) +{ + size_t pos = CityHash_v1_0_2::Hash128to64(CityHash_v1_0_2::uint128(hash, hash_seed)) % (8 * size); + filter[pos / (8 * sizeof(UnderType))] |= (1ULL << (pos % (8 * sizeof(UnderType)))); +} + +bool BloomFilter::findHashWithSeed(const UInt64 & hash, const UInt64 & hash_seed) +{ + size_t pos = CityHash_v1_0_2::Hash128to64(CityHash_v1_0_2::uint128(hash, hash_seed)) % (8 * size); + return bool(filter[pos / (8 * sizeof(UnderType))] & (1ULL << (pos % (8 * sizeof(UnderType))))); +} + } diff --git a/dbms/src/Interpreters/BloomFilter.h b/dbms/src/Interpreters/BloomFilter.h index 1825dbec4bd..19469834c94 100644 --- a/dbms/src/Interpreters/BloomFilter.h +++ b/dbms/src/Interpreters/BloomFilter.h @@ -1,15 +1,17 @@ #pragma once -#include #include - +#include +#include +#include +#include namespace DB { -/// Bloom filter for strings. -class StringBloomFilter +class BloomFilter { + public: using UnderType = UInt64; using Container = std::vector; @@ -17,16 +19,19 @@ public: /// size -- size of filter in bytes. /// hashes -- number of used hash functions. /// seed -- random seed for hash functions generation. - StringBloomFilter(size_t size_, size_t hashes_, size_t seed_); - StringBloomFilter(const StringBloomFilter & bloom_filter); + BloomFilter(size_t size_, size_t hashes_, size_t seed_); + BloomFilter(const BloomFilter & bloom_filter); bool find(const char * data, size_t len); void add(const char * data, size_t len); void clear(); + void addHashWithSeed(const UInt64 & hash, const UInt64 & hash_seed); + bool findHashWithSeed(const UInt64 & hash, const UInt64 & hash_seed); + /// Checks if this contains everything from another bloom filter. /// Bloom filters must have equal size and seed. - bool contains(const StringBloomFilter & bf); + bool contains(const BloomFilter & bf); const Container & getFilter() const { return filter; } Container & getFilter() { return filter; } @@ -34,7 +39,7 @@ public: /// For debug. UInt64 isEmpty() const; - friend bool operator== (const StringBloomFilter & a, const StringBloomFilter & b); + friend bool operator== (const BloomFilter & a, const BloomFilter & b); private: size_t size; @@ -44,7 +49,8 @@ private: Container filter; }; +using BloomFilterPtr = std::shared_ptr; -bool operator== (const StringBloomFilter & a, const StringBloomFilter & b); +bool operator== (const BloomFilter & a, const BloomFilter & b); } diff --git a/dbms/src/Interpreters/BloomFilterHash.h b/dbms/src/Interpreters/BloomFilterHash.h new file mode 100644 index 00000000000..a94bc8687eb --- /dev/null +++ b/dbms/src/Interpreters/BloomFilterHash.h @@ -0,0 +1,207 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int ILLEGAL_COLUMN; +} + +struct BloomFilterHash +{ + static constexpr UInt64 bf_hash_seed[15] = { + 13635471485423070496ULL, 10336109063487487899ULL, 17779957404565211594ULL, 8988612159822229247ULL, 4954614162757618085ULL, + 12980113590177089081ULL, 9263883436177860930ULL, 3656772712723269762ULL, 10362091744962961274ULL, 7582936617938287249ULL, + 15033938188484401405ULL, 18286745649494826751ULL, 6852245486148412312ULL, 8886056245089344681ULL, 10151472371158292780ULL + }; + + static ColumnPtr hashWithField(const IDataType * data_type, const Field & field) + { + WhichDataType which(data_type); + + if (which.isUInt() || which.isDateOrDateTime()) + return ColumnConst::create(ColumnUInt64::create(1, intHash64(field.safeGet())), 1); + else if (which.isInt() || which.isEnum()) + return ColumnConst::create(ColumnUInt64::create(1, intHash64(ext::bit_cast(field.safeGet()))), 1); + else if (which.isFloat32() || which.isFloat64()) + return ColumnConst::create(ColumnUInt64::create(1, intHash64(ext::bit_cast(field.safeGet()))), 1); + else if (which.isString() || which.isFixedString()) + { + const auto & value = field.safeGet(); + return ColumnConst::create(ColumnUInt64::create(1, CityHash_v1_0_2::CityHash64(value.data(), value.size())), 1); + } + else + throw Exception("Unexpected type " + data_type->getName() + " of bloom filter index.", ErrorCodes::LOGICAL_ERROR); + } + + static ColumnPtr hashWithColumn(const DataTypePtr & data_type, const ColumnPtr & column, size_t pos, size_t limit) + { + auto index_column = ColumnUInt64::create(limit); + ColumnUInt64::Container & index_column_vec = index_column->getData(); + getAnyTypeHash(&*data_type, &*column, index_column_vec, pos); + return index_column; + } + + template + static void getAnyTypeHash(const IDataType * data_type, const IColumn * column, ColumnUInt64::Container & vec, size_t pos) + { + WhichDataType which(data_type); + + if (which.isUInt8()) getNumberTypeHash(column, vec, pos); + else if (which.isUInt16()) getNumberTypeHash(column, vec, pos); + else if (which.isUInt32()) getNumberTypeHash(column, vec, pos); + else if (which.isUInt64()) getNumberTypeHash(column, vec, pos); + else if (which.isInt8()) getNumberTypeHash(column, vec, pos); + else if (which.isInt16()) getNumberTypeHash(column, vec, pos); + else if (which.isInt32()) getNumberTypeHash(column, vec, pos); + else if (which.isInt64()) getNumberTypeHash(column, vec, pos); + else if (which.isEnum8()) getNumberTypeHash(column, vec, pos); + else if (which.isEnum16()) getNumberTypeHash(column, vec, pos); + else if (which.isDate()) getNumberTypeHash(column, vec, pos); + else if (which.isDateTime()) getNumberTypeHash(column, vec, pos); + else if (which.isFloat32()) getNumberTypeHash(column, vec, pos); + else if (which.isFloat64()) getNumberTypeHash(column, vec, pos); + else if (which.isString()) getStringTypeHash(column, vec, pos); + else if (which.isFixedString()) getStringTypeHash(column, vec, pos); + else throw Exception("Unexpected type " + data_type->getName() + " of bloom filter index.", ErrorCodes::LOGICAL_ERROR); + } + + template + static void getNumberTypeHash(const IColumn * column, ColumnUInt64::Container & vec, size_t pos) + { + const auto * index_column = typeid_cast *>(column); + + if (unlikely(!index_column)) + throw Exception("Illegal column type was passed to the bloom filter index.", ErrorCodes::ILLEGAL_COLUMN); + + const typename ColumnVector::Container & vec_from = index_column->getData(); + + /// Because we're missing the precision of float in the Field.h + /// to be consistent, we need to convert Float32 to Float64 processing, also see: BloomFilterHash::hashWithField + if constexpr (std::is_same_v, ColumnFloat32>) + { + for (size_t index = 0, size = vec.size(); index < size; ++index) + { + UInt64 hash = intHash64(ext::bit_cast(Float64(vec_from[index + pos]))); + + if constexpr (is_first) + vec[index] = hash; + else + vec[index] = CityHash_v1_0_2::Hash128to64(CityHash_v1_0_2::uint128(vec[index], hash)); + } + } + else + { + for (size_t index = 0, size = vec.size(); index < size; ++index) + { + UInt64 hash = intHash64(ext::bit_cast(vec_from[index + pos])); + + if constexpr (is_first) + vec[index] = hash; + else + vec[index] = CityHash_v1_0_2::Hash128to64(CityHash_v1_0_2::uint128(vec[index], hash)); + } + } + } + + template + static void getStringTypeHash(const IColumn * column, ColumnUInt64::Container & vec, size_t pos) + { + if (const auto * index_column = typeid_cast(column)) + { + const ColumnString::Chars & data = index_column->getChars(); + const ColumnString::Offsets & offsets = index_column->getOffsets(); + + ColumnString::Offset current_offset = pos; + for (size_t index = 0, size = vec.size(); index < size; ++index) + { + UInt64 city_hash = CityHash_v1_0_2::CityHash64( + reinterpret_cast(&data[current_offset]), offsets[index + pos] - current_offset - 1); + + if constexpr (is_first) + vec[index] = city_hash; + else + vec[index] = CityHash_v1_0_2::Hash128to64(CityHash_v1_0_2::uint128(vec[index], city_hash)); + + current_offset = offsets[index + pos]; + } + } + else if (const auto * fixed_string_index_column = typeid_cast(column)) + { + size_t fixed_len = fixed_string_index_column->getN(); + const auto & data = fixed_string_index_column->getChars(); + + for (size_t index = 0, size = vec.size(); index < size; ++index) + { + UInt64 city_hash = CityHash_v1_0_2::CityHash64(reinterpret_cast(&data[(index + pos) * fixed_len]), fixed_len); + + if constexpr (is_first) + vec[index] = city_hash; + else + vec[index] = CityHash_v1_0_2::Hash128to64(CityHash_v1_0_2::uint128(vec[index], city_hash)); + } + } + else + throw Exception("Illegal column type was passed to the bloom filter index.", ErrorCodes::ILLEGAL_COLUMN); + } + + static std::pair calculationBestPractices(double max_conflict_probability) + { + static const size_t MAX_BITS_PER_ROW = 20; + static const size_t MAX_HASH_FUNCTION_COUNT = 15; + + /// For the smallest index per level in probability_lookup_table + static const size_t min_probability_index_each_bits[] = {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14}; + + static const long double probability_lookup_table[MAX_BITS_PER_ROW + 1][MAX_HASH_FUNCTION_COUNT] = + { + {1.0}, /// dummy, 0 bits per row + {1.0, 1.0}, + {1.0, 0.393, 0.400}, + {1.0, 0.283, 0.237, 0.253}, + {1.0, 0.221, 0.155, 0.147, 0.160}, + {1.0, 0.181, 0.109, 0.092, 0.092, 0.101}, // 5 + {1.0, 0.154, 0.0804, 0.0609, 0.0561, 0.0578, 0.0638}, + {1.0, 0.133, 0.0618, 0.0423, 0.0359, 0.0347, 0.0364}, + {1.0, 0.118, 0.0489, 0.0306, 0.024, 0.0217, 0.0216, 0.0229}, + {1.0, 0.105, 0.0397, 0.0228, 0.0166, 0.0141, 0.0133, 0.0135, 0.0145}, + {1.0, 0.0952, 0.0329, 0.0174, 0.0118, 0.00943, 0.00844, 0.00819, 0.00846}, // 10 + {1.0, 0.0869, 0.0276, 0.0136, 0.00864, 0.0065, 0.00552, 0.00513, 0.00509}, + {1.0, 0.08, 0.0236, 0.0108, 0.00646, 0.00459, 0.00371, 0.00329, 0.00314}, + {1.0, 0.074, 0.0203, 0.00875, 0.00492, 0.00332, 0.00255, 0.00217, 0.00199, 0.00194}, + {1.0, 0.0689, 0.0177, 0.00718, 0.00381, 0.00244, 0.00179, 0.00146, 0.00129, 0.00121, 0.0012}, + {1.0, 0.0645, 0.0156, 0.00596, 0.003, 0.00183, 0.00128, 0.001, 0.000852, 0.000775, 0.000744}, // 15 + {1.0, 0.0606, 0.0138, 0.005, 0.00239, 0.00139, 0.000935, 0.000702, 0.000574, 0.000505, 0.00047, 0.000459}, + {1.0, 0.0571, 0.0123, 0.00423, 0.00193, 0.00107, 0.000692, 0.000499, 0.000394, 0.000335, 0.000302, 0.000287, 0.000284}, + {1.0, 0.054, 0.0111, 0.00362, 0.00158, 0.000839, 0.000519, 0.00036, 0.000275, 0.000226, 0.000198, 0.000183, 0.000176}, + {1.0, 0.0513, 0.00998, 0.00312, 0.0013, 0.000663, 0.000394, 0.000264, 0.000194, 0.000155, 0.000132, 0.000118, 0.000111, 0.000109}, + {1.0, 0.0488, 0.00906, 0.0027, 0.00108, 0.00053, 0.000303, 0.000196, 0.00014, 0.000108, 8.89e-05, 7.77e-05, 7.12e-05, 6.79e-05, 6.71e-05} // 20 + }; + + for (size_t bits_per_row = 1; bits_per_row < MAX_BITS_PER_ROW; ++bits_per_row) + { + if (probability_lookup_table[bits_per_row][min_probability_index_each_bits[bits_per_row]] <= max_conflict_probability) + { + size_t max_size_of_hash_functions = min_probability_index_each_bits[bits_per_row]; + for (size_t size_of_hash_functions = max_size_of_hash_functions; size_of_hash_functions > 0; --size_of_hash_functions) + if (probability_lookup_table[bits_per_row][size_of_hash_functions] > max_conflict_probability) + return std::pair(bits_per_row, size_of_hash_functions + 1); + } + } + + return std::pair(MAX_BITS_PER_ROW - 1, min_probability_index_each_bits[MAX_BITS_PER_ROW - 1]); + } +}; + +} diff --git a/dbms/src/Interpreters/Cluster.cpp b/dbms/src/Interpreters/Cluster.cpp index d550151a645..3c7c9bbe9da 100644 --- a/dbms/src/Interpreters/Cluster.cpp +++ b/dbms/src/Interpreters/Cluster.cpp @@ -1,8 +1,8 @@ #include +#include #include #include #include -#include #include #include #include @@ -29,9 +29,9 @@ namespace /// Default shard weight. static constexpr UInt32 default_weight = 1; -inline bool isLocal(const Cluster::Address & address, const Poco::Net::SocketAddress & resolved_address, UInt16 clickhouse_port) +inline bool isLocalImpl(const Cluster::Address & address, const Poco::Net::SocketAddress & resolved_address, UInt16 clickhouse_port) { - /// If there is replica, for which: + /// If there is replica, for which: /// - its port is the same that the server is listening; /// - its host is resolved to set of addresses, one of which is the same as one of addresses of network interfaces of the server machine*; /// then we must go to this shard without any inter-process communication. @@ -48,10 +48,31 @@ inline bool isLocal(const Cluster::Address & address, const Poco::Net::SocketAdd /// Implementation of Cluster::Address class +std::optional Cluster::Address::getResolvedAddress() const +{ + try + { + return DNSResolver::instance().resolveAddress(host_name, port); + } + catch (...) + { + /// Failure in DNS resolution in cluster initialization is Ok. + tryLogCurrentException("Cluster"); + return {}; + } +} + + +bool Cluster::Address::isLocal(UInt16 clickhouse_port) const +{ + if (auto resolved = getResolvedAddress()) + return isLocalImpl(*this, *resolved, clickhouse_port); + return false; +} + + Cluster::Address::Address(const Poco::Util::AbstractConfiguration & config, const String & config_prefix) { - UInt16 clickhouse_port = static_cast(config.getInt("tcp_port", 0)); - host_name = config.getString(config_prefix + ".host"); port = static_cast(config.getInt(config_prefix + ".port")); if (config.has(config_prefix + ".user")) @@ -60,10 +81,9 @@ Cluster::Address::Address(const Poco::Util::AbstractConfiguration & config, cons user = config.getString(config_prefix + ".user", "default"); password = config.getString(config_prefix + ".password", ""); default_database = config.getString(config_prefix + ".default_database", ""); - initially_resolved_address = DNSResolver::instance().resolveAddress(host_name, port); - is_local = isLocal(*this, initially_resolved_address, clickhouse_port); secure = config.getBool(config_prefix + ".secure", false) ? Protocol::Secure::Enable : Protocol::Secure::Disable; compression = config.getBool(config_prefix + ".compression", true) ? Protocol::Compression::Enable : Protocol::Compression::Disable; + is_local = isLocal(config.getInt("tcp_port", 0)); } @@ -74,9 +94,7 @@ Cluster::Address::Address(const String & host_port_, const String & user_, const host_name = parsed_host_port.first; port = parsed_host_port.second; secure = secure_ ? Protocol::Secure::Enable : Protocol::Secure::Disable; - - initially_resolved_address = DNSResolver::instance().resolveAddress(parsed_host_port.first, parsed_host_port.second); - is_local = isLocal(*this, initially_resolved_address, clickhouse_port); + is_local = isLocal(clickhouse_port); } diff --git a/dbms/src/Interpreters/Cluster.h b/dbms/src/Interpreters/Cluster.h index 06714da5cef..e778c9bcf6f 100644 --- a/dbms/src/Interpreters/Cluster.h +++ b/dbms/src/Interpreters/Cluster.h @@ -60,7 +60,7 @@ public: /// This database is selected when no database is specified for Distributed table String default_database; /// The locality is determined at the initialization, and is not changed even if DNS is changed - bool is_local; + bool is_local = false; bool user_specified = false; Protocol::Compression compression = Protocol::Compression::Enable; @@ -84,17 +84,14 @@ public: String toFullString() const; static Address fromFullString(const String & address_full_string); - /// Returns initially resolved address - Poco::Net::SocketAddress getResolvedAddress() const - { - return initially_resolved_address; - } + /// Returns resolved address if it does resolve. + std::optional getResolvedAddress() const; auto tuple() const { return std::tie(host_name, port, secure, user, password, default_database); } bool operator==(const Address & other) const { return tuple() == other.tuple(); } private: - Poco::Net::SocketAddress initially_resolved_address; + bool isLocal(UInt16 clickhouse_port) const; }; using Addresses = std::vector
; diff --git a/dbms/src/Interpreters/Context.cpp b/dbms/src/Interpreters/Context.cpp index bbeba97aaad..bf779ada6b4 100644 --- a/dbms/src/Interpreters/Context.cpp +++ b/dbms/src/Interpreters/Context.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -244,15 +245,12 @@ struct ContextShared return; shutdown_called = true; - { - std::lock_guard lock(mutex); + /** After system_logs have been shut down it is guaranteed that no system table gets created or written to. + * Note that part changes at shutdown won't be logged to part log. + */ - /** After this point, system logs will shutdown their threads and no longer write any data. - * It will prevent recreation of system tables at shutdown. - * Note that part changes at shutdown won't be logged to part log. - */ - system_logs.reset(); - } + if (system_logs) + system_logs->shutdown(); /** At this point, some tables may have threads that block our mutex. * To shutdown them correctly, we will copy the current list of tables, @@ -280,6 +278,7 @@ struct ContextShared /// Preemptive destruction is important, because these objects may have a refcount to ContextShared (cyclic reference). /// TODO: Get rid of this. + system_logs.reset(); embedded_dictionaries.reset(); external_dictionaries.reset(); external_models.reset(); @@ -1459,6 +1458,12 @@ zkutil::ZooKeeperPtr Context::getZooKeeper() const return shared->zookeeper; } +void Context::resetZooKeeper() const +{ + std::lock_guard lock(shared->zookeeper_mutex); + shared->zookeeper.reset(); +} + bool Context::hasZooKeeper() const { return getConfigRef().has("zookeeper"); @@ -1774,6 +1779,11 @@ BlockOutputStreamPtr Context::getOutputFormat(const String & name, WriteBuffer & return FormatFactory::instance().getOutput(name, buf, sample, *this); } +OutputFormatPtr Context::getOutputFormatProcessor(const String & name, WriteBuffer & buf, const Block & sample) const +{ + return FormatFactory::instance().getOutputFormat(name, buf, sample, *this); +} + time_t Context::getUptimeSeconds() const { @@ -1848,6 +1858,25 @@ Context::SampleBlockCache & Context::getSampleBlockCache() const } +bool Context::hasQueryParameters() const +{ + return !query_parameters.empty(); +} + + +const NameToNameMap & Context::getQueryParameters() const +{ + return query_parameters; +} + + +void Context::setQueryParameter(const String & name, const String & value) +{ + if (!query_parameters.emplace(name, value).second) + throw Exception("Duplicate name " + backQuote(name) + " of query parameter", ErrorCodes::BAD_ARGUMENTS); +} + + #if USE_EMBEDDED_COMPILER std::shared_ptr Context::getCompiledExpressionCache() const diff --git a/dbms/src/Interpreters/Context.h b/dbms/src/Interpreters/Context.h index 50f9dd1ca36..44547f97ef2 100644 --- a/dbms/src/Interpreters/Context.h +++ b/dbms/src/Interpreters/Context.h @@ -74,6 +74,8 @@ class ShellCommand; class ICompressionCodec; class SettingsConstraints; +class IOutputFormat; +using OutputFormatPtr = std::shared_ptr; #if USE_EMBEDDED_COMPILER @@ -133,7 +135,7 @@ private: Tables table_function_results; /// Temporary tables obtained by execution of table functions. Keyed by AST tree id. Context * query_context = nullptr; Context * session_context = nullptr; /// Session context or nullptr. Could be equal to this. - Context * global_context = nullptr; /// Global context or nullptr. Could be equal to this. + Context * global_context = nullptr; /// Global context. Could be equal to this. UInt64 session_close_cycle = 0; bool session_is_used = false; @@ -144,6 +146,9 @@ private: using DatabasePtr = std::shared_ptr; using Databases = std::map>; + NameToNameMap query_parameters; /// Dictionary with query parameters for prepared statements. + /// (key=name, value) + IHostContextPtr host_context; /// Arbitrary object that may used to attach some host specific information to query context, /// when using ClickHouse as a library in some project. For example, it may contain host /// logger, some query identification information, profiling guards, etc. This field is @@ -286,6 +291,8 @@ public: BlockInputStreamPtr getInputFormat(const String & name, ReadBuffer & buf, const Block & sample, UInt64 max_block_size) const; BlockOutputStreamPtr getOutputFormat(const String & name, WriteBuffer & buf, const Block & sample) const; + OutputFormatPtr getOutputFormatProcessor(const String & name, WriteBuffer & buf, const Block & sample) const; + InterserverIOHandler & getInterserverIOHandler(); /// How other servers can access this for downloading replicated data. @@ -341,7 +348,10 @@ public: void setQueryContext(Context & context_) { query_context = &context_; } void setSessionContext(Context & context_) { session_context = &context_; } - void setGlobalContext(Context & context_) { global_context = &context_; } + + void makeQueryContext() { query_context = this; } + void makeSessionContext() { session_context = this; } + void makeGlobalContext() { global_context = this; } const Settings & getSettingsRef() const { return settings; } Settings & getSettingsRef() { return settings; } @@ -370,6 +380,8 @@ public: std::shared_ptr getZooKeeper() const; /// Has ready or expired ZooKeeper bool hasZooKeeper() const; + /// Reset current zookeeper session. Do not create a new one. + void resetZooKeeper() const; /// Create a cache of uncompressed blocks of specified size. This can be done only once. void setUncompressedCache(size_t max_size_in_bytes); @@ -464,6 +476,11 @@ public: SampleBlockCache & getSampleBlockCache() const; + /// Query parameters for prepared statements. + bool hasQueryParameters() const; + const NameToNameMap & getQueryParameters() const; + void setQueryParameter(const String & name, const String & value); + #if USE_EMBEDDED_COMPILER std::shared_ptr getCompiledExpressionCache() const; void setCompiledExpressionCache(size_t cache_size); diff --git a/dbms/src/Interpreters/DDLWorker.cpp b/dbms/src/Interpreters/DDLWorker.cpp index e1cea632a37..1a4113a0d9c 100644 --- a/dbms/src/Interpreters/DDLWorker.cpp +++ b/dbms/src/Interpreters/DDLWorker.cpp @@ -506,8 +506,9 @@ void DDLWorker::parseQueryAndResolveHost(DDLTask & task) { const Cluster::Address & address = shards[shard_num][replica_num]; - if (isLocalAddress(address.getResolvedAddress(), context.getTCPPort()) - || (context.getTCPPortSecure() && isLocalAddress(address.getResolvedAddress(), *context.getTCPPortSecure()))) + if (auto resolved = address.getResolvedAddress(); + resolved && (isLocalAddress(*resolved, context.getTCPPort()) + || (context.getTCPPortSecure() && isLocalAddress(*resolved, *context.getTCPPortSecure())))) { if (found_via_resolving) { diff --git a/dbms/src/Interpreters/DNSCacheUpdater.cpp b/dbms/src/Interpreters/DNSCacheUpdater.cpp index 80ea1258f48..90c27ea2854 100644 --- a/dbms/src/Interpreters/DNSCacheUpdater.cpp +++ b/dbms/src/Interpreters/DNSCacheUpdater.cpp @@ -2,78 +2,30 @@ #include #include #include -#include -#include -#include - - -namespace ProfileEvents -{ - extern Event NetworkErrors; -} - namespace DB { -namespace ErrorCodes -{ - extern const int TIMEOUT_EXCEEDED; - extern const int ALL_CONNECTION_TRIES_FAILED; -} - - -/// Call it inside catch section -/// Returns true if it is a network error -static bool isNetworkError() -{ - try - { - throw; - } - catch (const Exception & e) - { - if (e.code() == ErrorCodes::TIMEOUT_EXCEEDED || e.code() == ErrorCodes::ALL_CONNECTION_TRIES_FAILED) - return true; - } - catch (Poco::Net::DNSException &) - { - return true; - } - catch (Poco::TimeoutException &) - { - return true; - } - catch (...) - { - /// Do nothing - } - - return false; -} - - -DNSCacheUpdater::DNSCacheUpdater(Context & context_) - : context(context_), pool(context_.getSchedulePool()) +DNSCacheUpdater::DNSCacheUpdater(Context & context_, Int32 update_period_seconds_) + : context(context_), + update_period_seconds(update_period_seconds_), + pool(context_.getSchedulePool()) { task_handle = pool.createTask("DNSCacheUpdater", [this]{ run(); }); } void DNSCacheUpdater::run() { - auto num_current_network_exceptions = ProfileEvents::global_counters[ProfileEvents::NetworkErrors].load(std::memory_order_relaxed); - if (num_current_network_exceptions >= last_num_network_erros + min_errors_to_update_cache) + auto & resolver = DNSResolver::instance(); + + /// Reload cluster config if IP of any host has been changed since last update. + if (resolver.updateCache()) { + LOG_INFO(&Poco::Logger::get("DNSCacheUpdater"), + "IPs of some hosts have been changed. Will reload cluster config."); try { - LOG_INFO(&Poco::Logger::get("DNSCacheUpdater"), "Updating DNS cache"); - - DNSResolver::instance().dropCache(); context.reloadClusterConfig(); - - last_num_network_erros = num_current_network_exceptions; - task_handle->scheduleAfter(min_update_period_seconds * 1000); - return; } catch (...) { @@ -81,19 +33,22 @@ void DNSCacheUpdater::run() } } - task_handle->scheduleAfter(10 * 1000); + /** DNS resolution may take a while and by this reason, actual update period will be longer than update_period_seconds. + * We intentionally allow this "drift" for two reasons: + * - automatically throttle when DNS requests take longer time; + * - add natural randomization on huge clusters - avoid sending all requests at the same moment of time from different servers. + */ + task_handle->scheduleAfter(update_period_seconds * 1000); } -bool DNSCacheUpdater::incrementNetworkErrorEventsIfNeeded() +void DNSCacheUpdater::start() { - if (isNetworkError()) - { - ProfileEvents::increment(ProfileEvents::NetworkErrors); - return true; - } + task_handle->activateAndSchedule(); +} - return false; +DNSCacheUpdater::~DNSCacheUpdater() +{ + task_handle->deactivate(); } } - diff --git a/dbms/src/Interpreters/DNSCacheUpdater.h b/dbms/src/Interpreters/DNSCacheUpdater.h index 6d34697c401..52577ad43f6 100644 --- a/dbms/src/Interpreters/DNSCacheUpdater.h +++ b/dbms/src/Interpreters/DNSCacheUpdater.h @@ -1,10 +1,6 @@ -#pragma once - -#include -#include -#include #include +#include namespace DB @@ -12,26 +8,22 @@ namespace DB class Context; -/// Add a task to BackgroundProcessingPool that watch for ProfileEvents::NetworkErrors and updates DNS cache if it has increased +/// Add a task to BackgroundProcessingPool that resolves all hosts and updates cache with constant period. class DNSCacheUpdater { public: - explicit DNSCacheUpdater(Context & context); - - /// Checks if it is a network error and increments ProfileEvents::NetworkErrors - static bool incrementNetworkErrorEventsIfNeeded(); + explicit DNSCacheUpdater(Context & context, Int32 update_period_seconds_); + ~DNSCacheUpdater(); + void start(); private: void run(); Context & context; + Int32 update_period_seconds; + BackgroundSchedulePool & pool; BackgroundSchedulePoolTaskHolder task_handle; - - size_t last_num_network_erros = 0; - - static constexpr size_t min_errors_to_update_cache = 3; - static constexpr time_t min_update_period_seconds = 45; }; diff --git a/dbms/src/Interpreters/ExecuteScalarSubqueriesVisitor.cpp b/dbms/src/Interpreters/ExecuteScalarSubqueriesVisitor.cpp index 88049565aeb..59f7f46be70 100644 --- a/dbms/src/Interpreters/ExecuteScalarSubqueriesVisitor.cpp +++ b/dbms/src/Interpreters/ExecuteScalarSubqueriesVisitor.cpp @@ -9,10 +9,12 @@ #include #include #include +#include #include #include + namespace DB { @@ -23,22 +25,6 @@ namespace ErrorCodes } -static ASTPtr addTypeConversion(std::unique_ptr && ast, const String & type_name) -{ - auto func = std::make_shared(); - ASTPtr res = func; - func->alias = ast->alias; - func->prefer_alias_to_column_name = ast->prefer_alias_to_column_name; - ast->alias.clear(); - func->name = "CAST"; - auto exp_list = std::make_shared(); - func->arguments = exp_list; - func->children.push_back(func->arguments); - exp_list->children.emplace_back(ast.release()); - exp_list->children.emplace_back(std::make_shared(type_name)); - return res; -} - bool ExecuteScalarSubqueriesMatcher::needChildVisit(ASTPtr & node, const ASTPtr & child) { /// Processed @@ -110,7 +96,7 @@ void ExecuteScalarSubqueriesMatcher::visit(const ASTSubquery & subquery, ASTPtr auto lit = std::make_unique((*block.safeGetByPosition(0).column)[0]); lit->alias = subquery.alias; lit->prefer_alias_to_column_name = subquery.prefer_alias_to_column_name; - ast = addTypeConversion(std::move(lit), block.safeGetByPosition(0).type->getName()); + ast = addTypeConversionToAST(std::move(lit), block.safeGetByPosition(0).type->getName()); } else { @@ -125,7 +111,7 @@ void ExecuteScalarSubqueriesMatcher::visit(const ASTSubquery & subquery, ASTPtr exp_list->children.resize(columns); for (size_t i = 0; i < columns; ++i) { - exp_list->children[i] = addTypeConversion( + exp_list->children[i] = addTypeConversionToAST( std::make_unique((*block.safeGetByPosition(i).column)[0]), block.safeGetByPosition(i).type->getName()); } diff --git a/dbms/src/Interpreters/ExpressionActions.cpp b/dbms/src/Interpreters/ExpressionActions.cpp index 135b3491806..43592c2616a 100644 --- a/dbms/src/Interpreters/ExpressionActions.cpp +++ b/dbms/src/Interpreters/ExpressionActions.cpp @@ -191,7 +191,7 @@ void ExpressionAction::prepare(Block & sample_block, const Settings & settings) { arguments[i] = sample_block.getPositionByName(argument_names[i]); ColumnPtr col = sample_block.safeGetByPosition(arguments[i]).column; - if (!col || !col->isColumnConst()) + if (!col || !isColumnConst(*col)) all_const = false; } @@ -215,7 +215,7 @@ void ExpressionAction::prepare(Block & sample_block, const Settings & settings) /// If the result is not a constant, just in case, we will consider the result as unknown. ColumnWithTypeAndName & col = sample_block.safeGetByPosition(result_position); - if (!col.column->isColumnConst()) + if (!isColumnConst(*col.column)) { col.column = nullptr; } @@ -610,14 +610,14 @@ void ExpressionActions::checkLimits(Block & block) const { size_t non_const_columns = 0; for (size_t i = 0, size = block.columns(); i < size; ++i) - if (block.safeGetByPosition(i).column && !block.safeGetByPosition(i).column->isColumnConst()) + if (block.safeGetByPosition(i).column && !isColumnConst(*block.safeGetByPosition(i).column)) ++non_const_columns; if (non_const_columns > settings.max_temporary_non_const_columns) { std::stringstream list_of_non_const_columns; for (size_t i = 0, size = block.columns(); i < size; ++i) - if (block.safeGetByPosition(i).column && !block.safeGetByPosition(i).column->isColumnConst()) + if (block.safeGetByPosition(i).column && !isColumnConst(*block.safeGetByPosition(i).column)) list_of_non_const_columns << "\n" << block.safeGetByPosition(i).name; throw Exception("Too many temporary non-const columns:" + list_of_non_const_columns.str() @@ -740,22 +740,27 @@ void ExpressionActions::execute(Block & block, bool dry_run) const } } +bool ExpressionActions::hasTotalsInJoin() const +{ + bool has_totals_in_join = false; + for (const auto & action : actions) + { + if (action.join && action.join->hasTotals()) + { + has_totals_in_join = true; + break; + } + } + + return has_totals_in_join; +} + void ExpressionActions::executeOnTotals(Block & block) const { /// If there is `totals` in the subquery for JOIN, but we do not have totals, then take the block with the default values instead of `totals`. if (!block) { - bool has_totals_in_join = false; - for (const auto & action : actions) - { - if (action.join && action.join->hasTotals()) - { - has_totals_in_join = true; - break; - } - } - - if (has_totals_in_join) + if (hasTotalsInJoin()) { for (const auto & name_and_type : input_columns) { diff --git a/dbms/src/Interpreters/ExpressionActions.h b/dbms/src/Interpreters/ExpressionActions.h index e8755d5f4ea..68cc3e73b17 100644 --- a/dbms/src/Interpreters/ExpressionActions.h +++ b/dbms/src/Interpreters/ExpressionActions.h @@ -223,6 +223,9 @@ public: /// Execute the expression on the block. The block must contain all the columns returned by getRequiredColumns. void execute(Block & block, bool dry_run = false) const; + /// Check if joined subquery has totals. + bool hasTotalsInJoin() const; + /** Execute the expression on the block of total values. * Almost the same as `execute`. The difference is only when JOIN is executed. */ diff --git a/dbms/src/Interpreters/ExpressionAnalyzer.cpp b/dbms/src/Interpreters/ExpressionAnalyzer.cpp index 5c9b31c2c70..20b4beb0789 100644 --- a/dbms/src/Interpreters/ExpressionAnalyzer.cpp +++ b/dbms/src/Interpreters/ExpressionAnalyzer.cpp @@ -144,7 +144,11 @@ void ExpressionAnalyzer::analyzeAggregation() { getRootActions(array_join_expression_list, true, temp_actions); addMultipleArrayJoinAction(temp_actions, is_array_join_left); - array_join_columns = temp_actions->getSampleBlock().getNamesAndTypesList(); + + array_join_columns.clear(); + for (auto & column : temp_actions->getSampleBlock().getNamesAndTypesList()) + if (syntax->array_join_result_to_source.count(column.name)) + array_join_columns.emplace_back(column); } const ASTTablesInSelectQueryElement * join = select_query->join(); @@ -186,7 +190,7 @@ void ExpressionAnalyzer::analyzeAggregation() const auto & col = block.getByName(column_name); /// Constant expressions have non-null column pointer at this stage. - if (col.column && col.column->isColumnConst()) + if (col.column && isColumnConst(*col.column)) { /// But don't remove last key column if no aggregate functions, otherwise aggregation will not work. if (!aggregate_descriptions.empty() || size > 1) @@ -275,12 +279,14 @@ void ExpressionAnalyzer::tryMakeSetForIndexFromSubquery(const ASTPtr & subquery_ SetPtr set = std::make_shared(settings.size_limits_for_set, true); set->setHeader(res.in->getHeader()); + res.in->readPrefix(); while (Block block = res.in->read()) { /// If the limits have been exceeded, give up and let the default subquery processing actions take place. if (!set->insertFromBlock(block)) return; } + res.in->readSuffix(); prepared_sets[set_key] = std::move(set); } diff --git a/dbms/src/Interpreters/ExpressionAnalyzer.h b/dbms/src/Interpreters/ExpressionAnalyzer.h index 6bba6860f6f..52c43dda90f 100644 --- a/dbms/src/Interpreters/ExpressionAnalyzer.h +++ b/dbms/src/Interpreters/ExpressionAnalyzer.h @@ -249,7 +249,7 @@ private: void assertAggregation() const; /** - * Create Set from a subuquery or a table expression in the query. The created set is suitable for using the index. + * Create Set from a subquery or a table expression in the query. The created set is suitable for using the index. * The set will not be created if its size hits the limit. */ void tryMakeSetForIndexFromSubquery(const ASTPtr & subquery_or_table_name); diff --git a/dbms/src/Interpreters/ExpressionJIT.cpp b/dbms/src/Interpreters/ExpressionJIT.cpp index 9779a2df993..1b030fbd3cd 100644 --- a/dbms/src/Interpreters/ExpressionJIT.cpp +++ b/dbms/src/Interpreters/ExpressionJIT.cpp @@ -85,7 +85,7 @@ namespace static ColumnData getColumnData(const IColumn * column) { ColumnData result; - const bool is_const = column->isColumnConst(); + const bool is_const = isColumnConst(*column); if (is_const) column = &reinterpret_cast(column)->getDataColumn(); if (auto * nullable = typeid_cast(column)) diff --git a/dbms/src/Interpreters/ExternalLoader.cpp b/dbms/src/Interpreters/ExternalLoader.cpp index 658f17b531d..c34193f71e4 100644 --- a/dbms/src/Interpreters/ExternalLoader.cpp +++ b/dbms/src/Interpreters/ExternalLoader.cpp @@ -343,25 +343,6 @@ public: enable_async_loading = enable; } - /// Returns the names of all the objects in the configuration (loaded or not). - std::vector getNames() const - { - std::lock_guard lock{mutex}; - std::vector all_names; - for (const auto & name_and_info : infos) - { - const String & name = name_and_info.first; - all_names.emplace_back(name); - } - return all_names; - } - - size_t getNumberOfNames() const - { - std::lock_guard lock{mutex}; - return infos.size(); - } - /// Returns the status of the object. /// If the object has not been loaded yet then the function returns Status::NOT_LOADED. /// If the specified name isn't found in the configuration then the function returns Status::NOT_EXIST. @@ -419,6 +400,15 @@ public: return count; } + bool hasCurrentlyLoadedObjects() const + { + std::lock_guard lock{mutex}; + for (auto & name_info : infos) + if (name_info.second.loaded()) + return true; + return false; + } + /// Starts loading of a specified object. void load(const String & name) { @@ -1008,14 +998,9 @@ void ExternalLoader::enablePeriodicUpdates(bool enable_, const ExternalLoaderUpd periodic_updater->enable(enable_, settings_); } -std::vector ExternalLoader::getNames() const +bool ExternalLoader::hasCurrentlyLoadedObjects() const { - return loading_dispatcher->getNames(); -} - -size_t ExternalLoader::getNumberOfNames() const -{ - return loading_dispatcher->getNumberOfNames(); + return loading_dispatcher->hasCurrentlyLoadedObjects(); } ExternalLoader::Status ExternalLoader::getCurrentStatus(const String & name) const @@ -1053,6 +1038,11 @@ size_t ExternalLoader::getNumberOfCurrentlyLoadedObjects() const return loading_dispatcher->getNumberOfCurrentlyLoadedObjects(); } +void ExternalLoader::load(const String & name) const +{ + loading_dispatcher->load(name); +} + void ExternalLoader::load(const String & name, LoadablePtr & loaded_object, Duration timeout) const { loading_dispatcher->load(name, loaded_object, timeout); @@ -1073,6 +1063,11 @@ void ExternalLoader::loadStrict(const String & name, LoadResult & load_result) c loading_dispatcher->loadStrict(name, load_result); } +void ExternalLoader::load(const FilterByNameFunction & filter_by_name) const +{ + loading_dispatcher->load(filter_by_name); +} + void ExternalLoader::load(const FilterByNameFunction & filter_by_name, Loadables & loaded_objects, Duration timeout) const { if (filter_by_name) @@ -1089,6 +1084,11 @@ void ExternalLoader::load(const FilterByNameFunction & filter_by_name, LoadResul loading_dispatcher->load(load_results, timeout); } +void ExternalLoader::load() const +{ + loading_dispatcher->load(); +} + void ExternalLoader::load(Loadables & loaded_objects, Duration timeout) const { return loading_dispatcher->load(loaded_objects, timeout); diff --git a/dbms/src/Interpreters/ExternalLoader.h b/dbms/src/Interpreters/ExternalLoader.h index 8fe565c7667..da999bfe21a 100644 --- a/dbms/src/Interpreters/ExternalLoader.h +++ b/dbms/src/Interpreters/ExternalLoader.h @@ -107,10 +107,6 @@ public: /// Sets settings for periodic updates. void enablePeriodicUpdates(bool enable, const ExternalLoaderUpdateSettings & settings = {}); - /// Returns the names of all the objects in the configuration (loaded or not). - std::vector getNames() const; - size_t getNumberOfNames() const; - /// Returns the status of the object. /// If the object has not been loaded yet then the function returns Status::NOT_LOADED. /// If the specified name isn't found in the configuration then the function returns Status::NOT_EXIST. @@ -133,6 +129,9 @@ public: Loadables getCurrentlyLoadedObjects(const FilterByNameFunction & filter_by_name) const; size_t getNumberOfCurrentlyLoadedObjects() const; + /// Returns true if any object was loaded. + bool hasCurrentlyLoadedObjects() const; + static constexpr Duration NO_TIMEOUT = Duration::max(); /// Starts loading of a specified object. diff --git a/dbms/src/Interpreters/GlobalSubqueriesVisitor.h b/dbms/src/Interpreters/GlobalSubqueriesVisitor.h index 4b94a804858..229fa00a59f 100644 --- a/dbms/src/Interpreters/GlobalSubqueriesVisitor.h +++ b/dbms/src/Interpreters/GlobalSubqueriesVisitor.h @@ -92,7 +92,7 @@ public: Block sample = interpreter->getSampleBlock(); NamesAndTypesList columns = sample.getNamesAndTypesList(); - StoragePtr external_storage = StorageMemory::create(external_table_name, ColumnsDescription{columns}); + StoragePtr external_storage = StorageMemory::create("_external", external_table_name, ColumnsDescription{columns}); external_storage->startup(); /** We replace the subquery with the name of the temporary table. diff --git a/dbms/src/Interpreters/IInterpreter.h b/dbms/src/Interpreters/IInterpreter.h index b51e773a17b..e1090061cf3 100644 --- a/dbms/src/Interpreters/IInterpreter.h +++ b/dbms/src/Interpreters/IInterpreter.h @@ -2,6 +2,7 @@ #include +#include namespace DB { @@ -17,6 +18,10 @@ public: */ virtual BlockIO execute() = 0; + virtual QueryPipeline executeWithProcessors() { throw Exception("executeWithProcessors not implemented", ErrorCodes::NOT_IMPLEMENTED); } + + virtual bool canExecuteWithProcessors() const { return false; } + virtual ~IInterpreter() {} }; diff --git a/dbms/src/Interpreters/InterpreterCheckQuery.cpp b/dbms/src/Interpreters/InterpreterCheckQuery.cpp index c99c74fa33a..3edcc12fedc 100644 --- a/dbms/src/Interpreters/InterpreterCheckQuery.cpp +++ b/dbms/src/Interpreters/InterpreterCheckQuery.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -11,6 +12,21 @@ namespace DB { +namespace +{ + +NamesAndTypes getBlockStructure() +{ + return { + {"part_path", std::make_shared()}, + {"is_passed", std::make_shared()}, + {"message", std::make_shared()}, + }; +} + +} + + InterpreterCheckQuery::InterpreterCheckQuery(const ASTPtr & query_ptr_, const Context & context_) : query_ptr(query_ptr_), context(context_) { @@ -19,18 +35,32 @@ InterpreterCheckQuery::InterpreterCheckQuery(const ASTPtr & query_ptr_, const Co BlockIO InterpreterCheckQuery::execute() { - const auto & alter = query_ptr->as(); - const String & table_name = alter.table; - String database_name = alter.database.empty() ? context.getCurrentDatabase() : alter.database; + const auto & check = query_ptr->as(); + const String & table_name = check.table; + String database_name = check.database.empty() ? context.getCurrentDatabase() : check.database; StoragePtr table = context.getTable(database_name, table_name); + auto check_results = table->checkData(query_ptr, context); - auto column = ColumnUInt8::create(); - column->insertValue(UInt64(table->checkData())); - result = Block{{ std::move(column), std::make_shared(), "result" }}; + auto block_structure = getBlockStructure(); + auto path_column = block_structure[0].type->createColumn(); + auto is_passed_column = block_structure[1].type->createColumn(); + auto message_column = block_structure[2].type->createColumn(); + + for (const auto & check_result : check_results) + { + path_column->insert(check_result.fs_path); + is_passed_column->insert(static_cast(check_result.success)); + message_column->insert(check_result.failure_message); + } + + Block block({ + {std::move(path_column), block_structure[0].type, block_structure[0].name}, + {std::move(is_passed_column), block_structure[1].type, block_structure[1].name}, + {std::move(message_column), block_structure[2].type, block_structure[2].name}}); BlockIO res; - res.in = std::make_shared(result); + res.in = std::make_shared(block); return res; } diff --git a/dbms/src/Interpreters/InterpreterCreateQuery.cpp b/dbms/src/Interpreters/InterpreterCreateQuery.cpp index 973023cd4b2..7e1f46e674e 100644 --- a/dbms/src/Interpreters/InterpreterCreateQuery.cpp +++ b/dbms/src/Interpreters/InterpreterCreateQuery.cpp @@ -1,9 +1,6 @@ #include -#include - #include -#include #include #include @@ -44,10 +41,10 @@ #include #include -#include - #include + #include +#include namespace DB @@ -281,19 +278,25 @@ ColumnsDescription InterpreterCreateQuery::getColumnsDescription(const ASTExpres /// add column to postprocessing if there is a default_expression specified if (col_decl.default_expression) { - /** for columns with explicitly-specified type create two expressions: - * 1. default_expression aliased as column name with _tmp suffix - * 2. conversion of expression (1) to explicitly-specified type alias as column name */ + /** For columns with explicitly-specified type create two expressions: + * 1. default_expression aliased as column name with _tmp suffix + * 2. conversion of expression (1) to explicitly-specified type alias as column name + */ if (col_decl.type) { const auto & final_column_name = col_decl.name; const auto tmp_column_name = final_column_name + "_tmp"; const auto data_type_ptr = column_names_and_types.back().type.get(); - default_expr_list->children.emplace_back(setAlias( - makeASTFunction("CAST", std::make_shared(tmp_column_name), - std::make_shared(data_type_ptr->getName())), final_column_name)); - default_expr_list->children.emplace_back(setAlias(col_decl.default_expression->clone(), tmp_column_name)); + + default_expr_list->children.emplace_back( + setAlias(addTypeConversionToAST(std::make_shared(tmp_column_name), data_type_ptr->getName()), + final_column_name)); + + default_expr_list->children.emplace_back( + setAlias( + col_decl.default_expression->clone(), + tmp_column_name)); } else default_expr_list->children.emplace_back(setAlias(col_decl.default_expression->clone(), col_decl.name)); @@ -332,7 +335,7 @@ ColumnsDescription InterpreterCreateQuery::getColumnsDescription(const ASTExpres column.type = name_type_it->type; if (!column.type->equals(*deduced_type)) - default_expr = makeASTFunction("CAST", default_expr, std::make_shared(column.type->getName())); + default_expr = addTypeConversionToAST(std::move(default_expr), column.type->getName()); } else column.type = defaults_sample_block.getByName(column.name).type; @@ -622,7 +625,7 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create) insert->select = create.select->clone(); if (create.temporary && !context.getSessionContext().hasQueryContext()) - context.getSessionContext().setQueryContext(context.getSessionContext()); + context.getSessionContext().makeQueryContext(); return InterpreterInsertQuery(insert, create.temporary ? context.getSessionContext() : context, diff --git a/dbms/src/Interpreters/InterpreterInsertQuery.cpp b/dbms/src/Interpreters/InterpreterInsertQuery.cpp index e4391f52247..b906d151415 100644 --- a/dbms/src/Interpreters/InterpreterInsertQuery.cpp +++ b/dbms/src/Interpreters/InterpreterInsertQuery.cpp @@ -57,8 +57,6 @@ StoragePtr InterpreterInsertQuery::getTable(const ASTInsertQuery & query) Block InterpreterInsertQuery::getSampleBlock(const ASTInsertQuery & query, const StoragePtr & table) { - - Block table_sample_non_materialized = table->getSampleBlockNonMaterialized(); /// If the query does not include information about columns if (!query.columns) @@ -66,6 +64,8 @@ Block InterpreterInsertQuery::getSampleBlock(const ASTInsertQuery & query, const /// Format Native ignores header and write blocks as is. if (query.format == "Native") return {}; + else if (query.no_destination) + return table->getSampleBlockWithVirtuals(); else return table_sample_non_materialized; } @@ -108,14 +108,14 @@ BlockIO InterpreterInsertQuery::execute() if (!(context.getSettingsRef().insert_distributed_sync && table->isRemote())) { out = std::make_shared( - out, table->getSampleBlock(), context.getSettingsRef().min_insert_block_size_rows, context.getSettingsRef().min_insert_block_size_bytes); + out, out->getHeader(), context.getSettingsRef().min_insert_block_size_rows, context.getSettingsRef().min_insert_block_size_bytes); } auto query_sample_block = getSampleBlock(query, table); /// Actually we don't know structure of input blocks from query/table, /// because some clients break insertion protocol (columns != header) out = std::make_shared( - out, query_sample_block, table->getSampleBlock(), table->getColumns().getDefaults(), context); + out, query_sample_block, out->getHeader(), table->getColumns().getDefaults(), context); auto out_wrapper = std::make_shared(out); out_wrapper->setProcessListElement(context.getProcessListElement()); diff --git a/dbms/src/Interpreters/InterpreterKillQueryQuery.cpp b/dbms/src/Interpreters/InterpreterKillQueryQuery.cpp index 89339668088..4e4120c5580 100644 --- a/dbms/src/Interpreters/InterpreterKillQueryQuery.cpp +++ b/dbms/src/Interpreters/InterpreterKillQueryQuery.cpp @@ -265,6 +265,11 @@ Block InterpreterKillQueryQuery::getSelectResult(const String & columns, const S if (where_expression) select_query += " WHERE " + queryToString(where_expression); + auto use_processors = context.getSettingsRef().experimental_use_processors; + context.getSettingsRef().experimental_use_processors = false; + + SCOPE_EXIT(context.getSettingsRef().experimental_use_processors = use_processors); + BlockIO block_io = executeQuery(select_query, context, true); Block res = block_io.in->read(); diff --git a/dbms/src/Interpreters/InterpreterSelectQuery.cpp b/dbms/src/Interpreters/InterpreterSelectQuery.cpp index bab04df70ab..d6e46fbedb3 100644 --- a/dbms/src/Interpreters/InterpreterSelectQuery.cpp +++ b/dbms/src/Interpreters/InterpreterSelectQuery.cpp @@ -58,6 +58,26 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + namespace DB { @@ -356,6 +376,13 @@ BlockInputStreams InterpreterSelectQuery::executeWithMultipleStreams() return pipeline.streams; } +QueryPipeline InterpreterSelectQuery::executeWithProcessors() +{ + QueryPipeline query_pipeline; + executeImpl(query_pipeline, input, options.only_analyze); + return query_pipeline; +} + InterpreterSelectQuery::AnalysisResult InterpreterSelectQuery::analyzeExpressions(QueryProcessingStage::Enum from_stage, bool dry_run, const FilterInfoPtr & filter_info) { @@ -555,7 +582,8 @@ InterpreterSelectQuery::analyzeExpressions(QueryProcessingStage::Enum from_stage } -void InterpreterSelectQuery::executeImpl(Pipeline & pipeline, const BlockInputStreamPtr & prepared_input, bool dry_run) +template +void InterpreterSelectQuery::executeImpl(TPipeline & pipeline, const BlockInputStreamPtr & prepared_input, bool dry_run) { /** Streams of data. When the query is executed in parallel, we have several data streams. * If there is no GROUP BY, then perform all operations before ORDER BY and LIMIT in parallel, then @@ -567,6 +595,8 @@ void InterpreterSelectQuery::executeImpl(Pipeline & pipeline, const BlockInputSt * then perform the remaining operations with one resulting stream. */ + constexpr bool pipeline_with_processors = std::is_same::value; + /// Now we will compose block streams that perform the necessary actions. auto & query = getSelectQuery(); const Settings & settings = context.getSettingsRef(); @@ -611,21 +641,42 @@ void InterpreterSelectQuery::executeImpl(Pipeline & pipeline, const BlockInputSt if (dry_run) { - pipeline.streams.emplace_back(std::make_shared(source_header)); + if constexpr (pipeline_with_processors) + pipeline.init({std::make_shared(source_header)}); + else + pipeline.streams.emplace_back(std::make_shared(source_header)); + expressions = analyzeExpressions(QueryProcessingStage::FetchColumns, true, filter_info); if (storage && expressions.filter_info && expressions.prewhere_info) throw Exception("PREWHERE is not supported if the table is filtered by row-level security expression", ErrorCodes::ILLEGAL_PREWHERE); if (expressions.prewhere_info) - pipeline.streams.back() = std::make_shared( + { + if constexpr (pipeline_with_processors) + pipeline.addSimpleTransform([&](const Block & header) + { + return std::make_shared( + header, + expressions.prewhere_info->prewhere_actions, + expressions.prewhere_info->prewhere_column_name, + expressions.prewhere_info->remove_prewhere_column); + }); + else + pipeline.streams.back() = std::make_shared( pipeline.streams.back(), expressions.prewhere_info->prewhere_actions, expressions.prewhere_info->prewhere_column_name, expressions.prewhere_info->remove_prewhere_column); + } } else { if (prepared_input) - pipeline.streams.push_back(prepared_input); + { + if constexpr (pipeline_with_processors) + pipeline.init({std::make_shared(prepared_input)}); + else + pipeline.streams.push_back(prepared_input); + } expressions = analyzeExpressions(from_stage, false, filter_info); @@ -662,25 +713,78 @@ void InterpreterSelectQuery::executeImpl(Pipeline & pipeline, const BlockInputSt { if (expressions.filter_info) { - pipeline.transform([&](auto & stream) + if constexpr (pipeline_with_processors) { - stream = std::make_shared( - stream, - expressions.filter_info->actions, - expressions.filter_info->column_name, - expressions.filter_info->do_remove_column); - }); + pipeline.addSimpleTransform([&](const Block & block, QueryPipeline::StreamType stream_type) -> ProcessorPtr + { + if (stream_type == QueryPipeline::StreamType::Totals) + return nullptr; + + return std::make_shared( + block, + expressions.filter_info->actions, + expressions.filter_info->column_name, + expressions.filter_info->do_remove_column); + }); + } + else + { + pipeline.transform([&](auto & stream) + { + stream = std::make_shared( + stream, + expressions.filter_info->actions, + expressions.filter_info->column_name, + expressions.filter_info->do_remove_column); + }); + } } if (expressions.hasJoin()) { + Block header_before_join; + + if constexpr (pipeline_with_processors) + { + header_before_join = pipeline.getHeader(); + + /// In case joined subquery has totals, and we don't, add default chunk to totals. + bool default_totals = false; + if (!pipeline.hasTotals()) + { + pipeline.addDefaultTotals(); + default_totals = true; + } + + pipeline.addSimpleTransform([&](const Block & header, QueryPipeline::StreamType type) + { + bool on_totals = type == QueryPipeline::StreamType::Totals; + return std::make_shared(header, expressions.before_join, on_totals, default_totals); + }); + } + else + { + header_before_join = pipeline.firstStream()->getHeader(); + /// Applies to all sources except stream_with_non_joined_data. + for (auto & stream : pipeline.streams) + stream = std::make_shared(stream, expressions.before_join); + } + const auto & join = query.join()->table_join->as(); if (isRightOrFull(join.kind)) - pipeline.stream_with_non_joined_data = expressions.before_join->createStreamWithNonJoinedDataIfFullOrRightJoin( - pipeline.firstStream()->getHeader(), settings.max_block_size); + { + auto stream = expressions.before_join->createStreamWithNonJoinedDataIfFullOrRightJoin( + header_before_join, settings.max_block_size); - for (auto & stream : pipeline.streams) /// Applies to all sources except stream_with_non_joined_data. - stream = std::make_shared(stream, expressions.before_join); + if constexpr (pipeline_with_processors) + { + auto source = std::make_shared(std::move(stream)); + pipeline.addDelayedStream(source); + } + else + pipeline.stream_with_non_joined_data = std::move(stream); + + } } if (expressions.has_where) @@ -810,13 +914,18 @@ void InterpreterSelectQuery::executeImpl(Pipeline & pipeline, const BlockInputSt if (need_second_distinct_pass || query.limitLength() || query.limitBy() - || pipeline.stream_with_non_joined_data) + || pipeline.hasDelayedStream()) { need_merge_streams = true; } if (need_merge_streams) - executeUnion(pipeline); + { + if constexpr (pipeline_with_processors) + pipeline.resize(1); + else + executeUnion(pipeline); + } /** If there was more than one stream, * then DISTINCT needs to be performed once again after merging all streams. @@ -888,10 +997,13 @@ static UInt64 getLimitForSorting(const ASTSelectQuery & query, const Context & c } +template void InterpreterSelectQuery::executeFetchColumns( - QueryProcessingStage::Enum processing_stage, Pipeline & pipeline, + QueryProcessingStage::Enum processing_stage, TPipeline & pipeline, const PrewhereInfoPtr & prewhere_info, const Names & columns_to_remove_after_prewhere) { + constexpr bool pipeline_with_processors = std::is_same::value; + auto & query = getSelectQuery(); const Settings & settings = context.getSettingsRef(); @@ -1105,7 +1217,7 @@ void InterpreterSelectQuery::executeFetchColumns( throw Exception("Setting 'max_block_size' cannot be zero", ErrorCodes::PARAMETER_OUT_OF_BOUND); /// Initialize the initial data streams to which the query transforms are superimposed. Table or subquery or prepared input? - if (!pipeline.streams.empty()) + if (pipeline.initialized()) { /// Prepared input. } @@ -1127,7 +1239,11 @@ void InterpreterSelectQuery::executeFetchColumns( interpreter_subquery->ignoreWithTotals(); } - pipeline.streams = interpreter_subquery->executeWithMultipleStreams(); + if constexpr (pipeline_with_processors) + /// Just use pipeline from subquery. + pipeline = interpreter_subquery->executeWithProcessors(); + else + pipeline.streams = interpreter_subquery->executeWithMultipleStreams(); } else if (storage) { @@ -1146,27 +1262,23 @@ void InterpreterSelectQuery::executeFetchColumns( query_info.sets = query_analyzer->getPreparedSets(); query_info.prewhere_info = prewhere_info; - pipeline.streams = storage->read(required_columns, query_info, context, processing_stage, max_block_size, max_streams); + auto streams = storage->read(required_columns, query_info, context, processing_stage, max_block_size, max_streams); - if (pipeline.streams.empty()) + if (streams.empty()) { - pipeline.streams = {std::make_shared(storage->getSampleBlockForColumns(required_columns))}; + streams = {std::make_shared(storage->getSampleBlockForColumns(required_columns))}; if (query_info.prewhere_info) - pipeline.transform([&](auto & stream) - { - stream = std::make_shared( - stream, - prewhere_info->prewhere_actions, - prewhere_info->prewhere_column_name, - prewhere_info->remove_prewhere_column); - }); + streams.back() = std::make_shared( + streams.back(), + prewhere_info->prewhere_actions, + prewhere_info->prewhere_column_name, + prewhere_info->remove_prewhere_column); + } - pipeline.transform([&](auto & stream) - { + for (auto & stream : streams) stream->addTableLock(table_lock); - }); /// Set the limits and quota for reading data, the speed and time of the query. { @@ -1194,15 +1306,52 @@ void InterpreterSelectQuery::executeFetchColumns( QuotaForIntervals & quota = context.getQuota(); - pipeline.transform([&](auto & stream) + for (auto & stream : streams) { if (!options.ignore_limits) stream->setLimits(limits); if (options.to_stage == QueryProcessingStage::Complete) stream->setQuota(quota); - }); + } } + + if constexpr (pipeline_with_processors) + { + /// Unify streams. They must have same headers. + if (streams.size() > 1) + { + /// Unify streams in case they have different headers. + auto first_header = streams.at(0)->getHeader(); + for (size_t i = 1; i < streams.size(); ++i) + { + auto & stream = streams[i]; + auto header = stream->getHeader(); + auto mode = ConvertingBlockInputStream::MatchColumnsMode::Name; + if (!blocksHaveEqualStructure(first_header, header)) + stream = std::make_shared(context, stream, first_header, mode); + } + } + + Processors sources; + sources.reserve(streams.size()); + + for (auto & stream : streams) + { + bool force_add_agg_info = processing_stage == QueryProcessingStage::WithMergeableState; + auto source = std::make_shared(stream, force_add_agg_info); + + if (processing_stage == QueryProcessingStage::Complete) + source->addTotalsPort(); + + sources.emplace_back(std::move(source)); + + } + + pipeline.init(std::move(sources)); + } + else + pipeline.streams = std::move(streams); } else throw Exception("Logical error in InterpreterSelectQuery: nowhere to read", ErrorCodes::LOGICAL_ERROR); @@ -1210,10 +1359,20 @@ void InterpreterSelectQuery::executeFetchColumns( /// Aliases in table declaration. if (processing_stage == QueryProcessingStage::FetchColumns && alias_actions) { - pipeline.transform([&](auto & stream) + if constexpr (pipeline_with_processors) { - stream = std::make_shared(stream, alias_actions); - }); + pipeline.addSimpleTransform([&](const Block & header) + { + return std::make_shared(header, alias_actions); + }); + } + else + { + pipeline.transform([&](auto & stream) + { + stream = std::make_shared(stream, alias_actions); + }); + } } } @@ -1226,6 +1385,13 @@ void InterpreterSelectQuery::executeWhere(Pipeline & pipeline, const ExpressionA }); } +void InterpreterSelectQuery::executeWhere(QueryPipeline & pipeline, const ExpressionActionsPtr & expression, bool remove_fiter) +{ + pipeline.addSimpleTransform([&](const Block & block) + { + return std::make_shared(block, expression, getSelectQuery().where()->getColumnName(), remove_fiter); + }); +} void InterpreterSelectQuery::executeAggregation(Pipeline & pipeline, const ExpressionActionsPtr & expression, bool overflow_row, bool final) { @@ -1294,6 +1460,76 @@ void InterpreterSelectQuery::executeAggregation(Pipeline & pipeline, const Expre } +void InterpreterSelectQuery::executeAggregation(QueryPipeline & pipeline, const ExpressionActionsPtr & expression, bool overflow_row, bool final) +{ + pipeline.addSimpleTransform([&](const Block & header) + { + return std::make_shared(header, expression); + }); + + Names key_names; + AggregateDescriptions aggregates; + query_analyzer->getAggregateInfo(key_names, aggregates); + + Block header_before_aggregation = pipeline.getHeader(); + ColumnNumbers keys; + for (const auto & name : key_names) + keys.push_back(header_before_aggregation.getPositionByName(name)); + for (auto & descr : aggregates) + if (descr.arguments.empty()) + for (const auto & name : descr.argument_names) + descr.arguments.push_back(header_before_aggregation.getPositionByName(name)); + + const Settings & settings = context.getSettingsRef(); + + /** Two-level aggregation is useful in two cases: + * 1. Parallel aggregation is done, and the results should be merged in parallel. + * 2. An aggregation is done with store of temporary data on the disk, and they need to be merged in a memory efficient way. + */ + bool allow_to_use_two_level_group_by = pipeline.getNumMainStreams() > 1 || settings.max_bytes_before_external_group_by != 0; + + Aggregator::Params params(header_before_aggregation, keys, aggregates, + overflow_row, settings.max_rows_to_group_by, settings.group_by_overflow_mode, + settings.compile ? &context.getCompiler() : nullptr, settings.min_count_to_compile, + allow_to_use_two_level_group_by ? settings.group_by_two_level_threshold : SettingUInt64(0), + allow_to_use_two_level_group_by ? settings.group_by_two_level_threshold_bytes : SettingUInt64(0), + settings.max_bytes_before_external_group_by, settings.empty_result_for_aggregation_by_empty_set, + context.getTemporaryPath(), settings.max_threads); + + auto transform_params = std::make_shared(params, final); + + pipeline.dropTotalsIfHas(); + + /// If there are several sources, then we perform parallel aggregation + if (pipeline.getNumMainStreams() > 1) + { + pipeline.resize(max_streams); + + auto many_data = std::make_shared(max_streams); + auto merge_threads = settings.aggregation_memory_efficient_merge_threads + ? static_cast(settings.aggregation_memory_efficient_merge_threads) + : static_cast(settings.max_threads); + + size_t counter = 0; + pipeline.addSimpleTransform([&](const Block & header) + { + return std::make_shared(header, transform_params, many_data, counter++, max_streams, merge_threads); + }); + + pipeline.resize(1); + } + else + { + pipeline.resize(1); + + pipeline.addSimpleTransform([&](const Block & header) + { + return std::make_shared(header, transform_params); + }); + } +} + + void InterpreterSelectQuery::executeMergeAggregated(Pipeline & pipeline, bool overflow_row, bool final) { Names key_names; @@ -1345,6 +1581,67 @@ void InterpreterSelectQuery::executeMergeAggregated(Pipeline & pipeline, bool ov } } +void InterpreterSelectQuery::executeMergeAggregated(QueryPipeline & pipeline, bool overflow_row, bool final) +{ + Names key_names; + AggregateDescriptions aggregates; + query_analyzer->getAggregateInfo(key_names, aggregates); + + Block header_before_merge = pipeline.getHeader(); + + ColumnNumbers keys; + for (const auto & name : key_names) + keys.push_back(header_before_merge.getPositionByName(name)); + + /** There are two modes of distributed aggregation. + * + * 1. In different threads read from the remote servers blocks. + * Save all the blocks in the RAM. Merge blocks. + * If the aggregation is two-level - parallelize to the number of buckets. + * + * 2. In one thread, read blocks from different servers in order. + * RAM stores only one block from each server. + * If the aggregation is a two-level aggregation, we consistently merge the blocks of each next level. + * + * The second option consumes less memory (up to 256 times less) + * in the case of two-level aggregation, which is used for large results after GROUP BY, + * but it can work more slowly. + */ + + const Settings & settings = context.getSettingsRef(); + + Aggregator::Params params(header_before_merge, keys, aggregates, overflow_row, settings.max_threads); + + auto transform_params = std::make_shared(params, final); + + if (!settings.distributed_aggregation_memory_efficient) + { + /// We union several sources into one, parallelizing the work. + pipeline.resize(1); + + /// Now merge the aggregated blocks + pipeline.addSimpleTransform([&](const Block & header) + { + return std::make_shared(header, transform_params, settings.max_threads); + }); + } + else + { + /// pipeline.resize(max_streams); - Seem we don't need it. + auto num_merge_threads = settings.aggregation_memory_efficient_merge_threads + ? static_cast(settings.aggregation_memory_efficient_merge_threads) + : static_cast(settings.max_threads); + + auto pipe = createMergingAggregatedMemoryEfficientPipe( + pipeline.getHeader(), + transform_params, + pipeline.getNumStreams(), + num_merge_threads); + + pipeline.addPipe(std::move(pipe)); + } +} + void InterpreterSelectQuery::executeHaving(Pipeline & pipeline, const ExpressionActionsPtr & expression) { @@ -1354,6 +1651,18 @@ void InterpreterSelectQuery::executeHaving(Pipeline & pipeline, const Expression }); } +void InterpreterSelectQuery::executeHaving(QueryPipeline & pipeline, const ExpressionActionsPtr & expression) +{ + pipeline.addSimpleTransform([&](const Block & header, QueryPipeline::StreamType stream_type) -> ProcessorPtr + { + if (stream_type == QueryPipeline::StreamType::Totals) + return nullptr; + + /// TODO: do we need to save filter there? + return std::make_shared(header, expression, getSelectQuery().having()->getColumnName(), false); + }); +} + void InterpreterSelectQuery::executeTotalsAndHaving(Pipeline & pipeline, bool has_having, const ExpressionActionsPtr & expression, bool overflow_row, bool final) { @@ -1371,6 +1680,19 @@ void InterpreterSelectQuery::executeTotalsAndHaving(Pipeline & pipeline, bool ha final); } +void InterpreterSelectQuery::executeTotalsAndHaving(QueryPipeline & pipeline, bool has_having, const ExpressionActionsPtr & expression, bool overflow_row, bool final) +{ + const Settings & settings = context.getSettingsRef(); + + auto totals_having = std::make_shared( + pipeline.getHeader(), overflow_row, expression, + has_having ? getSelectQuery().having()->getColumnName() : "", + settings.totals_mode, settings.totals_auto_threshold, final); + + pipeline.addTotalsHavingTransform(std::move(totals_having)); +} + + void InterpreterSelectQuery::executeRollupOrCube(Pipeline & pipeline, Modificator modificator) { executeUnion(pipeline); @@ -1401,6 +1723,44 @@ void InterpreterSelectQuery::executeRollupOrCube(Pipeline & pipeline, Modificato pipeline.firstStream() = std::make_shared(pipeline.firstStream(), params); } +void InterpreterSelectQuery::executeRollupOrCube(QueryPipeline & pipeline, Modificator modificator) +{ + pipeline.resize(1); + + Names key_names; + AggregateDescriptions aggregates; + query_analyzer->getAggregateInfo(key_names, aggregates); + + Block header_before_transform = pipeline.getHeader(); + + ColumnNumbers keys; + + for (const auto & name : key_names) + keys.push_back(header_before_transform.getPositionByName(name)); + + const Settings & settings = context.getSettingsRef(); + + Aggregator::Params params(header_before_transform, keys, aggregates, + false, settings.max_rows_to_group_by, settings.group_by_overflow_mode, + settings.compile ? &context.getCompiler() : nullptr, settings.min_count_to_compile, + SettingUInt64(0), SettingUInt64(0), + settings.max_bytes_before_external_group_by, settings.empty_result_for_aggregation_by_empty_set, + context.getTemporaryPath(), settings.max_threads); + + auto transform_params = std::make_shared(params, true); + + pipeline.addSimpleTransform([&](const Block & header, QueryPipeline::StreamType stream_type) -> ProcessorPtr + { + if (stream_type == QueryPipeline::StreamType::Totals) + return nullptr; + + if (modificator == Modificator::ROLLUP) + return std::make_shared(header, std::move(transform_params)); + else + return std::make_shared(header, std::move(transform_params)); + }); +} + void InterpreterSelectQuery::executeExpression(Pipeline & pipeline, const ExpressionActionsPtr & expression) { @@ -1410,6 +1770,13 @@ void InterpreterSelectQuery::executeExpression(Pipeline & pipeline, const Expres }); } +void InterpreterSelectQuery::executeExpression(QueryPipeline & pipeline, const ExpressionActionsPtr & expression) +{ + pipeline.addSimpleTransform([&](const Block & header) -> ProcessorPtr + { + return std::make_shared(header, expression); + }); +} static SortDescription getSortDescription(const ASTSelectQuery & query) { @@ -1462,6 +1829,42 @@ void InterpreterSelectQuery::executeOrder(Pipeline & pipeline) settings.max_bytes_before_external_sort, context.getTemporaryPath()); } +void InterpreterSelectQuery::executeOrder(QueryPipeline & pipeline) +{ + auto & query = getSelectQuery(); + SortDescription order_descr = getSortDescription(query); + UInt64 limit = getLimitForSorting(query, context); + + const Settings & settings = context.getSettingsRef(); + + /// TODO: Limits on sorting +// IBlockInputStream::LocalLimits limits; +// limits.mode = IBlockInputStream::LIMITS_TOTAL; +// limits.size_limits = SizeLimits(settings.max_rows_to_sort, settings.max_bytes_to_sort, settings.sort_overflow_mode); + + + pipeline.addSimpleTransform([&](const Block & header, QueryPipeline::StreamType stream_type) + { + bool do_count_rows = stream_type == QueryPipeline::StreamType::Main; + return std::make_shared(header, order_descr, limit, do_count_rows); + }); + + /// If there are several streams, we merge them into one + pipeline.resize(1); + + /// Merge the sorted blocks. + pipeline.addSimpleTransform([&](const Block & header, QueryPipeline::StreamType stream_type) -> ProcessorPtr + { + if (stream_type == QueryPipeline::StreamType::Totals) + return nullptr; + + return std::make_shared( + header, order_descr, settings.max_block_size, limit, + settings.max_bytes_before_remerge_sort, + settings.max_bytes_before_external_sort, context.getTemporaryPath()); + }); +} + void InterpreterSelectQuery::executeMergeSorted(Pipeline & pipeline) { @@ -1490,6 +1893,27 @@ void InterpreterSelectQuery::executeMergeSorted(Pipeline & pipeline) } } +void InterpreterSelectQuery::executeMergeSorted(QueryPipeline & pipeline) +{ + auto & query = getSelectQuery(); + SortDescription order_descr = getSortDescription(query); + UInt64 limit = getLimitForSorting(query, context); + + const Settings & settings = context.getSettingsRef(); + + /// If there are several streams, then we merge them into one + if (pipeline.getNumStreams() > 1) + { + auto transform = std::make_shared( + pipeline.getHeader(), + pipeline.getNumStreams(), + order_descr, + settings.max_block_size, limit); + + pipeline.addPipe({ std::move(transform) }); + } +} + void InterpreterSelectQuery::executeProjection(Pipeline & pipeline, const ExpressionActionsPtr & expression) { @@ -1499,6 +1923,14 @@ void InterpreterSelectQuery::executeProjection(Pipeline & pipeline, const Expres }); } +void InterpreterSelectQuery::executeProjection(QueryPipeline & pipeline, const ExpressionActionsPtr & expression) +{ + pipeline.addSimpleTransform([&](const Block & header) -> ProcessorPtr + { + return std::make_shared(header, expression); + }); +} + void InterpreterSelectQuery::executeDistinct(Pipeline & pipeline, bool before_order, Names columns) { @@ -1522,6 +1954,32 @@ void InterpreterSelectQuery::executeDistinct(Pipeline & pipeline, bool before_or } } +void InterpreterSelectQuery::executeDistinct(QueryPipeline & pipeline, bool before_order, Names columns) +{ + auto & query = getSelectQuery(); + if (query.distinct) + { + const Settings & settings = context.getSettingsRef(); + + auto [limit_length, limit_offset] = getLimitLengthAndOffset(query, context); + UInt64 limit_for_distinct = 0; + + /// If after this stage of DISTINCT ORDER BY is not executed, then you can get no more than limit_length + limit_offset of different rows. + if (!query.orderBy() || !before_order) + limit_for_distinct = limit_length + limit_offset; + + SizeLimits limits(settings.max_rows_in_distinct, settings.max_bytes_in_distinct, settings.distinct_overflow_mode); + + pipeline.addSimpleTransform([&](const Block & header, QueryPipeline::StreamType stream_type) -> ProcessorPtr + { + if (stream_type == QueryPipeline::StreamType::Totals) + return nullptr; + + return std::make_shared(header, limits, limit_for_distinct, columns); + }); + } +} + void InterpreterSelectQuery::executeUnion(Pipeline & pipeline) { @@ -1558,6 +2016,24 @@ void InterpreterSelectQuery::executePreLimit(Pipeline & pipeline) } } +/// Preliminary LIMIT - is used in every source, if there are several sources, before they are combined. +void InterpreterSelectQuery::executePreLimit(QueryPipeline & pipeline) +{ + auto & query = getSelectQuery(); + /// If there is LIMIT + if (query.limitLength()) + { + auto [limit_length, limit_offset] = getLimitLengthAndOffset(query, context); + pipeline.addSimpleTransform([&, limit = limit_length + limit_offset](const Block & header, QueryPipeline::StreamType stream_type) -> ProcessorPtr + { + if (stream_type == QueryPipeline::StreamType::Totals) + return nullptr; + + return std::make_shared(header, limit, 0); + }); + } +} + void InterpreterSelectQuery::executeLimitBy(Pipeline & pipeline) { @@ -1577,6 +2053,28 @@ void InterpreterSelectQuery::executeLimitBy(Pipeline & pipeline) }); } +void InterpreterSelectQuery::executeLimitBy(QueryPipeline & pipeline) +{ + auto & query = getSelectQuery(); + if (!query.limitByLength() || !query.limitBy()) + return; + + Names columns; + for (const auto & elem : query.limitBy()->children) + columns.emplace_back(elem->getColumnName()); + + UInt64 length = getLimitUIntValue(query.limitByLength(), context); + UInt64 offset = (query.limitByOffset() ? getLimitUIntValue(query.limitByOffset(), context) : 0); + + pipeline.addSimpleTransform([&](const Block & header, QueryPipeline::StreamType stream_type) -> ProcessorPtr + { + if (stream_type == QueryPipeline::StreamType::Totals) + return nullptr; + + return std::make_shared(header, length, offset, columns); + }); +} + // TODO: move to anonymous namespace bool hasWithTotalsInAnySubqueryInFromClause(const ASTSelectQuery & query) @@ -1636,6 +2134,44 @@ void InterpreterSelectQuery::executeLimit(Pipeline & pipeline) } } +void InterpreterSelectQuery::executeLimit(QueryPipeline & pipeline) +{ + auto & query = getSelectQuery(); + /// If there is LIMIT + if (query.limitLength()) + { + /** Rare case: + * if there is no WITH TOTALS and there is a subquery in FROM, and there is WITH TOTALS on one of the levels, + * then when using LIMIT, you should read the data to the end, rather than cancel the query earlier, + * because if you cancel the query, we will not get `totals` data from the remote server. + * + * Another case: + * if there is WITH TOTALS and there is no ORDER BY, then read the data to the end, + * otherwise TOTALS is counted according to incomplete data. + */ + bool always_read_till_end = false; + + if (query.group_by_with_totals && !query.orderBy()) + always_read_till_end = true; + + if (!query.group_by_with_totals && hasWithTotalsInAnySubqueryInFromClause(query)) + always_read_till_end = true; + + UInt64 limit_length; + UInt64 limit_offset; + std::tie(limit_length, limit_offset) = getLimitLengthAndOffset(query, context); + + pipeline.addSimpleTransform([&](const Block & header, QueryPipeline::StreamType stream_type) -> ProcessorPtr + { + if (stream_type != QueryPipeline::StreamType::Main) + return nullptr; + + return std::make_shared( + header, limit_length, limit_offset, always_read_till_end); + }); + } +} + void InterpreterSelectQuery::executeExtremes(Pipeline & pipeline) { @@ -1648,6 +2184,15 @@ void InterpreterSelectQuery::executeExtremes(Pipeline & pipeline) }); } +void InterpreterSelectQuery::executeExtremes(QueryPipeline & pipeline) +{ + if (!context.getSettingsRef().extremes) + return; + + auto transform = std::make_shared(pipeline.getHeader()); + pipeline.addExtremesTransform(std::move(transform)); +} + void InterpreterSelectQuery::executeSubqueriesInSetsAndJoins(Pipeline & pipeline, SubqueriesForSets & subqueries_for_sets) { @@ -1656,6 +2201,19 @@ void InterpreterSelectQuery::executeSubqueriesInSetsAndJoins(Pipeline & pipeline pipeline.firstStream(), subqueries_for_sets, context); } +void InterpreterSelectQuery::executeSubqueriesInSetsAndJoins(QueryPipeline & pipeline, SubqueriesForSets & subqueries_for_sets) +{ + const Settings & settings = context.getSettingsRef(); + + auto creating_sets = std::make_shared( + pipeline.getHeader(), subqueries_for_sets, + SizeLimits(settings.max_rows_to_transfer, settings.max_bytes_to_transfer, settings.transfer_overflow_mode), + context); + + pipeline.addCreatingSetsTransform(std::move(creating_sets)); +} + + void InterpreterSelectQuery::unifyStreams(Pipeline & pipeline) { if (pipeline.hasMoreThanOneStream()) diff --git a/dbms/src/Interpreters/InterpreterSelectQuery.h b/dbms/src/Interpreters/InterpreterSelectQuery.h index 75747694d9e..8dda8589cd9 100644 --- a/dbms/src/Interpreters/InterpreterSelectQuery.h +++ b/dbms/src/Interpreters/InterpreterSelectQuery.h @@ -13,6 +13,7 @@ #include #include +#include namespace Poco { class Logger; } @@ -69,6 +70,9 @@ public: /// Execute the query and return multuple streams for parallel processing. BlockInputStreams executeWithMultipleStreams(); + QueryPipeline executeWithProcessors() override; + bool canExecuteWithProcessors() const override { return true; } + Block getSampleBlock(); void ignoreWithTotals(); @@ -125,10 +129,13 @@ private: { return hasMoreThanOneStream() || union_stream; } + + bool hasDelayedStream() const { return stream_with_non_joined_data != nullptr; } + bool initialized() const { return !streams.empty(); } }; - void executeImpl(Pipeline & pipeline, const BlockInputStreamPtr & prepared_input, bool dry_run); - + template + void executeImpl(TPipeline & pipeline, const BlockInputStreamPtr & prepared_input, bool dry_run); struct AnalysisResult { @@ -177,7 +184,8 @@ private: /// dry_run - don't read from table, use empty header block instead. void executeWithMultipleStreamsImpl(Pipeline & pipeline, const BlockInputStreamPtr & input, bool dry_run); - void executeFetchColumns(QueryProcessingStage::Enum processing_stage, Pipeline & pipeline, + template + void executeFetchColumns(QueryProcessingStage::Enum processing_stage, TPipeline & pipeline, const PrewhereInfoPtr & prewhere_info, const Names & columns_to_remove_after_prewhere); void executeWhere(Pipeline & pipeline, const ExpressionActionsPtr & expression, bool remove_filter); @@ -197,6 +205,22 @@ private: void executeExtremes(Pipeline & pipeline); void executeSubqueriesInSetsAndJoins(Pipeline & pipeline, std::unordered_map & subqueries_for_sets); + void executeWhere(QueryPipeline & pipeline, const ExpressionActionsPtr & expression, bool remove_fiter); + void executeAggregation(QueryPipeline & pipeline, const ExpressionActionsPtr & expression, bool overflow_row, bool final); + void executeMergeAggregated(QueryPipeline & pipeline, bool overflow_row, bool final); + void executeTotalsAndHaving(QueryPipeline & pipeline, bool has_having, const ExpressionActionsPtr & expression, bool overflow_row, bool final); + void executeHaving(QueryPipeline & pipeline, const ExpressionActionsPtr & expression); + void executeExpression(QueryPipeline & pipeline, const ExpressionActionsPtr & expression); + void executeOrder(QueryPipeline & pipeline); + void executeMergeSorted(QueryPipeline & pipeline); + void executePreLimit(QueryPipeline & pipeline); + void executeLimitBy(QueryPipeline & pipeline); + void executeLimit(QueryPipeline & pipeline); + void executeProjection(QueryPipeline & pipeline, const ExpressionActionsPtr & expression); + void executeDistinct(QueryPipeline & pipeline, bool before_order, Names columns); + void executeExtremes(QueryPipeline & pipeline); + void executeSubqueriesInSetsAndJoins(QueryPipeline & pipeline, std::unordered_map & subqueries_for_sets); + /// If pipeline has several streams with different headers, add ConvertingBlockInputStream to first header. void unifyStreams(Pipeline & pipeline); @@ -208,6 +232,8 @@ private: void executeRollupOrCube(Pipeline & pipeline, Modificator modificator); + void executeRollupOrCube(QueryPipeline & pipeline, Modificator modificator); + /** If there is a SETTINGS section in the SELECT query, then apply settings from it. * * Section SETTINGS - settings for a specific query. diff --git a/dbms/src/Interpreters/InterpreterSelectWithUnionQuery.cpp b/dbms/src/Interpreters/InterpreterSelectWithUnionQuery.cpp index 6e0a2603837..0899fed9872 100644 --- a/dbms/src/Interpreters/InterpreterSelectWithUnionQuery.cpp +++ b/dbms/src/Interpreters/InterpreterSelectWithUnionQuery.cpp @@ -12,6 +12,9 @@ #include #include +#include +#include + namespace DB { @@ -101,16 +104,25 @@ InterpreterSelectWithUnionQuery::InterpreterSelectWithUnionQuery( for (size_t query_num = 0; query_num < num_selects; ++query_num) headers[query_num] = nested_interpreters[query_num]->getSampleBlock(); - result_header = headers.front(); - size_t num_columns = result_header.columns(); + result_header = getCommonHeaderForUnion(headers); + } +} - for (size_t query_num = 1; query_num < num_selects; ++query_num) - if (headers[query_num].columns() != num_columns) - throw Exception("Different number of columns in UNION ALL elements:\n" - + result_header.dumpNames() - + "\nand\n" - + headers[query_num].dumpNames() + "\n", - ErrorCodes::UNION_ALL_RESULT_STRUCTURES_MISMATCH); + +Block InterpreterSelectWithUnionQuery::getCommonHeaderForUnion(const Blocks & headers) +{ + size_t num_selects = headers.size(); + Block common_header = headers.front(); + size_t num_columns = common_header.columns(); + + for (size_t query_num = 1; query_num < num_selects; ++query_num) + { + if (headers[query_num].columns() != num_columns) + throw Exception("Different number of columns in UNION ALL elements:\n" + + common_header.dumpNames() + + "\nand\n" + + headers[query_num].dumpNames() + "\n", + ErrorCodes::UNION_ALL_RESULT_STRUCTURES_MISMATCH); for (size_t column_num = 0; column_num < num_columns; ++column_num) { @@ -119,10 +131,12 @@ InterpreterSelectWithUnionQuery::InterpreterSelectWithUnionQuery( for (size_t i = 0; i < num_selects; ++i) columns.push_back(&headers[i].getByPosition(column_num)); - ColumnWithTypeAndName & result_elem = result_header.getByPosition(column_num); + ColumnWithTypeAndName & result_elem = common_header.getByPosition(column_num); result_elem = getLeastSuperColumn(columns); } } + + return common_header; } @@ -197,6 +211,43 @@ BlockIO InterpreterSelectWithUnionQuery::execute() } +QueryPipeline InterpreterSelectWithUnionQuery::executeWithProcessors() +{ + QueryPipeline main_pipeline; + std::vector pipelines; + bool has_main_pipeline = false; + + Blocks headers; + headers.reserve(nested_interpreters.size()); + + for (auto & interpreter : nested_interpreters) + { + if (!has_main_pipeline) + { + has_main_pipeline = true; + main_pipeline = interpreter->executeWithProcessors(); + headers.emplace_back(main_pipeline.getHeader()); + } + else + { + pipelines.emplace_back(interpreter->executeWithProcessors()); + headers.emplace_back(pipelines.back().getHeader()); + } + } + + if (!has_main_pipeline) + main_pipeline.init({ std::make_shared(getSampleBlock()) }); + + if (!pipelines.empty()) + { + auto common_header = getCommonHeaderForUnion(headers); + main_pipeline.unitePipelines(std::move(pipelines), common_header, context); + } + + return main_pipeline; +} + + void InterpreterSelectWithUnionQuery::ignoreWithTotals() { for (auto & interpreter : nested_interpreters) diff --git a/dbms/src/Interpreters/InterpreterSelectWithUnionQuery.h b/dbms/src/Interpreters/InterpreterSelectWithUnionQuery.h index 84d562a5308..9f2a4a96494 100644 --- a/dbms/src/Interpreters/InterpreterSelectWithUnionQuery.h +++ b/dbms/src/Interpreters/InterpreterSelectWithUnionQuery.h @@ -5,6 +5,7 @@ #include #include +#include namespace DB { @@ -30,6 +31,9 @@ public: /// Execute the query without union of streams. BlockInputStreams executeWithMultipleStreams(); + QueryPipeline executeWithProcessors() override; + bool canExecuteWithProcessors() const override { return true; } + Block getSampleBlock(); static Block getSampleBlock( @@ -48,6 +52,8 @@ private: std::vector> nested_interpreters; Block result_header; + + static Block getCommonHeaderForUnion(const Blocks & headers); }; } diff --git a/dbms/src/Interpreters/Join.cpp b/dbms/src/Interpreters/Join.cpp index 84bfcf475bc..cf23aef5b67 100644 --- a/dbms/src/Interpreters/Join.cpp +++ b/dbms/src/Interpreters/Join.cpp @@ -1,5 +1,5 @@ -#include -#include +#include + #include #include @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -32,7 +33,6 @@ namespace ErrorCodes extern const int ILLEGAL_COLUMN; } - static std::unordered_map requiredRightKeys(const Names & key_names, const NamesAndTypesList & columns_added_by_join) { NameSet right_keys; @@ -140,7 +140,7 @@ Join::Type Join::chooseMethod(const ColumnRawPtrs & key_columns, Sizes & key_siz /// If there is single string key, use hash table of it's values. if (keys_size == 1 && (typeid_cast(key_columns[0]) - || (key_columns[0]->isColumnConst() && typeid_cast(&static_cast(key_columns[0])->getDataColumn())))) + || (isColumnConst(*key_columns[0]) && typeid_cast(&static_cast(key_columns[0])->getDataColumn())))) return Type::key_string; if (keys_size == 1 && typeid_cast(key_columns[0])) @@ -226,8 +226,8 @@ void Join::init(Type type_) if (kind == ASTTableJoin::Kind::Cross) return; - dispatch(MapInitTag()); - dispatch([&](auto, auto, auto & map) { map.create(type); }); + joinDispatchInit(kind, strictness, maps); + joinDispatch(kind, strictness, maps, [&](auto, auto, auto & map) { map.create(type); }); } size_t Join::getTotalRowCount() const @@ -241,7 +241,7 @@ size_t Join::getTotalRowCount() const } else { - dispatch([&](auto, auto, auto & map) { res += map.getTotalRowCount(type); }); + joinDispatch(kind, strictness, maps, [&](auto, auto, auto & map) { res += map.getTotalRowCount(type); }); } return res; @@ -258,7 +258,7 @@ size_t Join::getTotalByteCount() const } else { - dispatch([&](auto, auto, auto & map) { res += map.getTotalByteCountImpl(type); }); + joinDispatch(kind, strictness, maps, [&](auto, auto, auto & map) { res += map.getTotalByteCountImpl(type); }); res += pool.size(); } @@ -289,8 +289,8 @@ void Join::setSampleBlock(const Block & block) } /// We will join only keys, where all components are not NULL. - if (key_columns[i]->isColumnNullable()) - key_columns[i] = &static_cast(*key_columns[i]).getNestedColumn(); + if (auto * nullable = checkAndGetColumn(*key_columns[i])) + key_columns[i] = &nullable->getNestedColumn(); } if (strictness == ASTTableJoin::Strictness::Asof) @@ -533,9 +533,8 @@ bool Join::insertFromBlock(const Block & block) } /// We will insert to the map only keys, where all components are not NULL. - ColumnPtr null_map_holder; ConstNullMapPtr null_map{}; - extractNestedColumnsAndNullMap(key_columns, null_map_holder, null_map); + ColumnPtr null_map_holder = extractNestedColumnsAndNullMap(key_columns, null_map); size_t rows = block.rows(); @@ -561,12 +560,23 @@ bool Join::insertFromBlock(const Block & block) if (kind != ASTTableJoin::Kind::Cross) { - dispatch([&](auto, auto strictness_, auto & map) + joinDispatch(kind, strictness, maps, [&](auto, auto strictness_, auto & map) { insertFromBlockImpl(*this, type, map, rows, key_columns, key_sizes, stored_block, null_map, pool); }); } + /// If RIGHT or FULL save blocks with nulls for NonJoinedBlockInputStream + if (isRightOrFull(kind) && null_map) + { + UInt8 has_null = 0; + for (size_t i = 0; !has_null && i < null_map->size(); ++i) + has_null |= (*null_map)[i]; + + if (has_null) + blocks_nullmaps.emplace_back(stored_block, null_map_holder); + } + return limits.check(getTotalRowCount(), getTotalByteCount(), "JOIN", ErrorCodes::SET_SIZE_LIMIT_EXCEEDED); } @@ -799,9 +809,8 @@ void Join::joinBlockImpl( } /// Keys with NULL value in any column won't join to anything. - ColumnPtr null_map_holder; ConstNullMapPtr null_map{}; - extractNestedColumnsAndNullMap(key_columns, null_map_holder, null_map); + ColumnPtr null_map_holder = extractNestedColumnsAndNullMap(key_columns, null_map); size_t existing_columns = block.columns(); @@ -1082,7 +1091,7 @@ void Join::joinBlock(Block & block, const Names & key_names_left, const NamesAnd checkTypesOfKeys(block, key_names_left, sample_block_with_keys); - if (dispatch([&](auto kind_, auto strictness_, auto & map) + if (joinDispatch(kind, strictness, maps, [&](auto kind_, auto strictness_, auto & map) { joinBlockImpl(block, key_names_left, columns_added_by_join, sample_block_with_columns_to_add, map); })) @@ -1169,7 +1178,8 @@ class NonJoinedBlockInputStream : public IBlockInputStream public: NonJoinedBlockInputStream(const Join & parent_, const Block & left_sample_block, const Names & key_names_left, const NamesAndTypesList & columns_added_by_join, UInt64 max_block_size_) - : parent(parent_), max_block_size(max_block_size_) + : parent(parent_) + , max_block_size(max_block_size_) { /** left_sample_block contains keys and "left" columns. * result_sample_block - keys, "left" columns, and "right" columns. @@ -1237,13 +1247,7 @@ protected: { if (parent.blocks.empty()) return Block(); - - Block block; - if (parent.dispatch([&](auto, auto strictness, auto & map) { block = createBlock(map); })) - ; - else - throw Exception("Logical error: unknown JOIN strictness (must be on of: ANY, ALL, ASOF)", ErrorCodes::LOGICAL_ERROR); - return block; + return createBlock(); } private: @@ -1259,7 +1263,8 @@ private: /// Which key columns need change nullability (right is nullable and left is not or vice versa) std::vector key_nullability_changes; - std::unique_ptr> position; /// type erasure + std::any position; + std::optional nulls_position; void makeResultSampleBlock(const Block & left_sample_block, const Block & right_sample_block, @@ -1307,8 +1312,7 @@ private: } } - template - Block createBlock(const Maps & maps) + Block createBlock() { MutableColumns columns_left = columnsForIndex(result_sample_block, column_indices_left); MutableColumns columns_keys_and_right = columnsForIndex(result_sample_block, column_indices_keys_and_right); @@ -1318,18 +1322,15 @@ private: size_t rows_added = 0; - switch (parent.type) + auto fill_callback = [&](auto, auto strictness, auto & map) { - #define M(TYPE) \ - case Join::Type::TYPE: \ - rows_added = fillColumns(*maps.TYPE, columns_keys_and_right); \ - break; - APPLY_FOR_JOIN_VARIANTS(M) - #undef M + rows_added = fillColumnsFromMap(map, columns_keys_and_right); + }; - default: - throw Exception("Unknown JOIN keys variant.", ErrorCodes::UNKNOWN_SET_DATA_VARIANT); - } + if (!joinDispatch(parent.kind, parent.strictness, parent.maps, fill_callback)) + throw Exception("Logical error: unknown JOIN strictness (must be on of: ANY, ALL, ASOF)", ErrorCodes::LOGICAL_ERROR); + + fillNullsFromBlocks(columns_keys_and_right, rows_added); if (!rows_added) return {}; @@ -1365,25 +1366,44 @@ private: return columns; } + template + size_t fillColumnsFromMap(const Maps & maps, MutableColumns & columns_keys_and_right) + { + switch (parent.type) + { + #define M(TYPE) \ + case Join::Type::TYPE: \ + return fillColumns(*maps.TYPE, columns_keys_and_right); + APPLY_FOR_JOIN_VARIANTS(M) + #undef M + default: + throw Exception("Unknown JOIN keys variant.", ErrorCodes::UNKNOWN_SET_DATA_VARIANT); + } + + __builtin_unreachable(); + } + template size_t fillColumns(const Map & map, MutableColumns & columns_keys_and_right) { + using Mapped = typename Map::mapped_type; + using Iterator = typename Map::const_iterator; + size_t rows_added = 0; - if (!position) - position = decltype(position)( - static_cast(new typename Map::const_iterator(map.begin())), //-V572 - [](void * ptr) { delete reinterpret_cast(ptr); }); + if (!position.has_value()) + position = std::make_any(map.begin()); - auto & it = *reinterpret_cast(position.get()); + Iterator & it = std::any_cast(position); auto end = map.end(); for (; it != end; ++it) { - if (it->getSecond().getUsed()) + const Mapped & mapped = it->getSecond(); + if (mapped.getUsed()) continue; - AdderNonJoined::add(it->getSecond(), rows_added, columns_keys_and_right); + AdderNonJoined::add(mapped, rows_added, columns_keys_and_right); if (rows_added >= max_block_size) { @@ -1395,6 +1415,30 @@ private: return rows_added; } + void fillNullsFromBlocks(MutableColumns & columns_keys_and_right, size_t & rows_added) + { + if (!nulls_position.has_value()) + nulls_position = parent.blocks_nullmaps.begin(); + + auto end = parent.blocks_nullmaps.end(); + + for (auto & it = *nulls_position; it != end && rows_added < max_block_size; ++it) + { + const Block * block = it->first; + const NullMap & nullmap = static_cast(*it->second).getData(); + + for (size_t row = 0; row < nullmap.size(); ++row) + { + if (nullmap[row]) + { + for (size_t col = 0; col < columns_keys_and_right.size(); ++col) + columns_keys_and_right[col]->insertFrom(*block->getByPosition(col).column, row); + ++rows_added; + } + } + } + } + static std::unordered_set getNullabilityChanges(const Block & sample_block_with_keys, const Block & out_block, const std::vector & key_positions, const std::unordered_map & left_to_right_key_map) @@ -1411,7 +1455,7 @@ private: const auto & dst = out_block.getByPosition(key_pos).column; const auto & src = sample_block_with_keys.getByPosition(i).column; - if (dst->isColumnNullable() != src->isColumnNullable()) + if (isColumnNullable(*dst) != isColumnNullable(*src)) nullability_changes.insert(key_pos); } @@ -1426,8 +1470,8 @@ private: if (changes_bitmap[i]) { ColumnPtr column = std::move(columns[i]); - if (column->isColumnNullable()) - column = static_cast(*column).getNestedColumnPtr(); + if (auto * nullable = checkAndGetColumn(*column)) + column = nullable->getNestedColumnPtr(); else column = makeNullable(column); diff --git a/dbms/src/Interpreters/Join.h b/dbms/src/Interpreters/Join.h index 4b3d699415c..f57755fad91 100644 --- a/dbms/src/Interpreters/Join.h +++ b/dbms/src/Interpreters/Join.h @@ -1,7 +1,9 @@ #pragma once +#include #include #include +#include #include @@ -19,8 +21,6 @@ #include #include -#include -#include namespace DB @@ -271,80 +271,7 @@ public: using MapsAllFull = MapsTemplate; using MapsAsof = MapsTemplate; - template - struct KindTrait - { - // Affects the Adder trait so that when the right part is empty, adding a default value on the left - static constexpr bool fill_left = static_in_v; - - // Affects the Map trait so that a `used` flag is attached to map slots in order to - // generate default values on the right when the left part is empty - static constexpr bool fill_right = static_in_v; - }; - - template - struct MapGetterImpl; - - template - using Map = typename MapGetterImpl::fill_right, strictness>::Map; - - static constexpr std::array STRICTNESSES - = {ASTTableJoin::Strictness::Any, ASTTableJoin::Strictness::All, ASTTableJoin::Strictness::Asof}; - static constexpr std::array KINDS - = {ASTTableJoin::Kind::Left, ASTTableJoin::Kind::Inner, ASTTableJoin::Kind::Full, ASTTableJoin::Kind::Right}; - - struct MapInitTag {}; - - template - bool dispatch(Func && func) - { - if (any_take_last_row) - { - return static_for<0, KINDS.size()>([&](auto i) - { - if (kind == KINDS[i] && strictness == ASTTableJoin::Strictness::Any) - { - if constexpr (std::is_same_v) - maps = Map(); - else - func( - std::integral_constant(), - std::integral_constant(), - std::get>(maps)); - return true; - } - return false; - }); - } - else - { - return static_for<0, KINDS.size() * STRICTNESSES.size()>([&](auto ij) - { - // NOTE: Avoid using nested static loop as GCC and CLANG have bugs in different ways - // See https://stackoverflow.com/questions/44386415/gcc-and-clang-disagree-about-c17-constexpr-lambda-captures - constexpr auto i = ij / STRICTNESSES.size(); - constexpr auto j = ij % STRICTNESSES.size(); - if (kind == KINDS[i] && strictness == STRICTNESSES[j]) - { - if constexpr (std::is_same_v) - maps = Map(); - else - func( - std::integral_constant(), - std::integral_constant(), - std::get>(maps)); - return true; - } - return false; - }); - } - } - - template - bool dispatch(Func && func) const - { - return const_cast(*this).dispatch(std::forward(func)); - } + using MapsVariant = std::variant; private: friend class NonJoinedBlockInputStream; @@ -362,16 +289,18 @@ private: /// Overwrite existing values when encountering the same key again bool any_take_last_row; - /** Blocks of "right" table. - */ + /// Blocks of "right" table. BlocksList blocks; - std::variant maps; + /// Nullmaps for blocks of "right" table (if needed) + using BlockNullmapList = std::deque>; + BlockNullmapList blocks_nullmaps; + + MapsVariant maps; /// Additional data - strings for string keys and continuation elements of single-linked lists of references to rows. Arena pool; -private: Type type = Type::EMPTY; std::optional asof_type; @@ -428,34 +357,4 @@ private: using JoinPtr = std::shared_ptr; using Joins = std::vector; -template <> -struct Join::MapGetterImpl -{ - using Map = MapsAny; -}; - -template <> -struct Join::MapGetterImpl -{ - using Map = MapsAnyFull; -}; - -template <> -struct Join::MapGetterImpl -{ - using Map = MapsAll; -}; - -template <> -struct Join::MapGetterImpl -{ - using Map = MapsAllFull; -}; - -template -struct Join::MapGetterImpl -{ - using Map = MapsAsof; -}; - } diff --git a/dbms/src/Interpreters/NullableUtils.cpp b/dbms/src/Interpreters/NullableUtils.cpp index dcb0657aa9d..9299a591afd 100644 --- a/dbms/src/Interpreters/NullableUtils.cpp +++ b/dbms/src/Interpreters/NullableUtils.cpp @@ -4,37 +4,38 @@ namespace DB { -void extractNestedColumnsAndNullMap(ColumnRawPtrs & key_columns, ColumnPtr & null_map_holder, ConstNullMapPtr & null_map) +ColumnPtr extractNestedColumnsAndNullMap(ColumnRawPtrs & key_columns, ConstNullMapPtr & null_map) { + ColumnPtr null_map_holder; + if (key_columns.size() == 1) { auto & column = key_columns[0]; - if (!column->isColumnNullable()) - return; - - const ColumnNullable & column_nullable = static_cast(*column); - null_map = &column_nullable.getNullMapData(); - column = &column_nullable.getNestedColumn(); + if (auto * column_nullable = checkAndGetColumn(*column)) + { + null_map_holder = column_nullable->getNullMapColumnPtr(); + null_map = &column_nullable->getNullMapData(); + column = &column_nullable->getNestedColumn(); + } } else { for (auto & column : key_columns) { - if (column->isColumnNullable()) + if (auto * column_nullable = checkAndGetColumn(*column)) { - const ColumnNullable & column_nullable = static_cast(*column); - column = &column_nullable.getNestedColumn(); + column = &column_nullable->getNestedColumn(); if (!null_map_holder) { - null_map_holder = column_nullable.getNullMapColumnPtr(); + null_map_holder = column_nullable->getNullMapColumnPtr(); } else { MutableColumnPtr mutable_null_map_holder = (*std::move(null_map_holder)).mutate(); PaddedPODArray & mutable_null_map = static_cast(*mutable_null_map_holder).getData(); - const PaddedPODArray & other_null_map = column_nullable.getNullMapData(); + const PaddedPODArray & other_null_map = column_nullable->getNullMapData(); for (size_t i = 0, size = mutable_null_map.size(); i < size; ++i) mutable_null_map[i] |= other_null_map[i]; @@ -45,6 +46,8 @@ void extractNestedColumnsAndNullMap(ColumnRawPtrs & key_columns, ColumnPtr & nul null_map = null_map_holder ? &static_cast(*null_map_holder).getData() : nullptr; } + + return null_map_holder; } } diff --git a/dbms/src/Interpreters/NullableUtils.h b/dbms/src/Interpreters/NullableUtils.h index e0689b853d7..ee3193919cd 100644 --- a/dbms/src/Interpreters/NullableUtils.h +++ b/dbms/src/Interpreters/NullableUtils.h @@ -6,8 +6,8 @@ namespace DB /** Replace Nullable key_columns to corresponding nested columns. * In 'null_map' return a map of positions where at least one column was NULL. - * null_map_holder could take ownership of null_map, if required. + * @returns ownership column of null_map. */ -void extractNestedColumnsAndNullMap(ColumnRawPtrs & key_columns, ColumnPtr & null_map_holder, ConstNullMapPtr & null_map); +ColumnPtr extractNestedColumnsAndNullMap(ColumnRawPtrs & key_columns, ConstNullMapPtr & null_map); } diff --git a/dbms/src/Interpreters/ProcessList.cpp b/dbms/src/Interpreters/ProcessList.cpp index a4fe438af8f..def39d4d91c 100644 --- a/dbms/src/Interpreters/ProcessList.cpp +++ b/dbms/src/Interpreters/ProcessList.cpp @@ -87,10 +87,9 @@ ProcessList::EntryPtr ProcessList::insert(const String & query_, const IAST * as { std::unique_lock lock(mutex); + const auto max_wait_ms = settings.queue_max_wait_ms.totalMilliseconds(); if (!is_unlimited_query && max_size && processes.size() >= max_size) { - auto max_wait_ms = settings.queue_max_wait_ms.totalMilliseconds(); - if (!max_wait_ms || !have_space.wait_for(lock, std::chrono::milliseconds(max_wait_ms), [&]{ return processes.size() < max_size; })) throw Exception("Too many simultaneous queries. Maximum: " + toString(max_size), ErrorCodes::TOO_MANY_SIMULTANEOUS_QUERIES); } @@ -117,20 +116,41 @@ ProcessList::EntryPtr ProcessList::insert(const String & query_, const IAST * as + ", maximum: " + settings.max_concurrent_queries_for_user.toString(), ErrorCodes::TOO_MANY_SIMULTANEOUS_QUERIES); - auto range = user_process_list->second.queries.equal_range(client_info.current_query_id); - if (range.first != range.second) + auto running_query = user_process_list->second.queries.find(client_info.current_query_id); + + if (running_query != user_process_list->second.queries.end()) { if (!settings.replace_running_query) throw Exception("Query with id = " + client_info.current_query_id + " is already running.", ErrorCodes::QUERY_WITH_SAME_ID_IS_ALREADY_RUNNING); /// Ask queries to cancel. They will check this flag. - for (auto it = range.first; it != range.second; ++it) - it->second->is_killed.store(true, std::memory_order_relaxed); - } + running_query->second->is_killed.store(true, std::memory_order_relaxed); + + if (!max_wait_ms || !have_space.wait_for(lock, std::chrono::milliseconds(max_wait_ms), [&] + { + running_query = user_process_list->second.queries.find(client_info.current_query_id); + if (running_query == user_process_list->second.queries.end()) + return true; + running_query->second->is_killed.store(true, std::memory_order_relaxed); + return false; + })) + throw Exception("Query with id = " + client_info.current_query_id + " is already running and can't be stopped", + ErrorCodes::QUERY_WITH_SAME_ID_IS_ALREADY_RUNNING); + } } } + /// Check other users running query with our query_id + for (const auto & user_process_list : user_to_queries) + { + if (user_process_list.first == client_info.current_user) + continue; + if (auto running_query = user_process_list.second.queries.find(client_info.current_query_id); running_query != user_process_list.second.queries.end()) + throw Exception("Query with id = " + client_info.current_query_id + " is already running by user " + user_process_list.first, + ErrorCodes::QUERY_WITH_SAME_ID_IS_ALREADY_RUNNING); + } + auto process_it = processes.emplace(processes.end(), query_, client_info, settings.max_memory_usage, settings.memory_tracker_fault_probability, priorities.insert(settings.priority)); @@ -226,17 +246,12 @@ ProcessListEntry::~ProcessListEntry() bool found = false; - auto range = user_process_list.queries.equal_range(query_id); - if (range.first != range.second) + if (auto running_query = user_process_list.queries.find(query_id); running_query != user_process_list.queries.end()) { - for (auto jt = range.first; jt != range.second; ++jt) + if (running_query->second == process_list_element_ptr) { - if (jt->second == process_list_element_ptr) - { - user_process_list.queries.erase(jt); - found = true; - break; - } + user_process_list.queries.erase(running_query->first); + found = true; } } @@ -245,8 +260,7 @@ ProcessListEntry::~ProcessListEntry() LOG_ERROR(&Logger::get("ProcessList"), "Logical error: cannot find query by query_id and pointer to ProcessListElement in ProcessListForUser"); std::terminate(); } - - parent.have_space.notify_one(); + parent.have_space.notify_all(); /// If there are no more queries for the user, then we will reset memory tracker and network throttler. if (user_process_list.queries.empty()) diff --git a/dbms/src/Interpreters/ProcessList.h b/dbms/src/Interpreters/ProcessList.h index 32f59749450..b75a4e7a730 100644 --- a/dbms/src/Interpreters/ProcessList.h +++ b/dbms/src/Interpreters/ProcessList.h @@ -203,7 +203,7 @@ struct ProcessListForUser ProcessListForUser(); /// query_id -> ProcessListElement(s). There can be multiple queries with the same query_id as long as all queries except one are cancelled. - using QueryToElement = std::unordered_multimap; + using QueryToElement = std::unordered_map; QueryToElement queries; ProfileEvents::Counters user_performance_counters{VariableContext::User, &ProfileEvents::global_counters}; diff --git a/dbms/src/Interpreters/QueryNormalizer.cpp b/dbms/src/Interpreters/QueryNormalizer.cpp index 1573202a946..c35c47179c6 100644 --- a/dbms/src/Interpreters/QueryNormalizer.cpp +++ b/dbms/src/Interpreters/QueryNormalizer.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ namespace ErrorCodes { extern const int TOO_DEEP_AST; extern const int CYCLIC_ALIASES; + extern const int UNKNOWN_QUERY_PARAMETER; } @@ -227,14 +229,16 @@ void QueryNormalizer::visit(ASTPtr & ast, Data & data) data.current_alias = my_alias; } - if (auto * node = ast->as()) - visit(*node, ast, data); - if (auto * node = ast->as()) - visit(*node, ast, data); - if (auto * node = ast->as()) - visit(*node, ast, data); - if (auto * node = ast->as()) - visit(*node, ast, data); + if (auto * node_func = ast->as()) + visit(*node_func, ast, data); + else if (auto * node_id = ast->as()) + visit(*node_id, ast, data); + else if (auto * node_tables = ast->as()) + visit(*node_tables, ast, data); + else if (auto * node_select = ast->as()) + visit(*node_select, ast, data); + else if (auto * node_param = ast->as()) + throw Exception("Query parameter " + backQuote(node_param->name) + " was not set", ErrorCodes::UNKNOWN_QUERY_PARAMETER); /// If we replace the root of the subtree, we will be called again for the new root, in case the alias is replaced by an alias. if (ast.get() != initial_ast.get()) diff --git a/dbms/src/Interpreters/QueryPriorities.h b/dbms/src/Interpreters/QueryPriorities.h index 5ded236e074..4a271510537 100644 --- a/dbms/src/Interpreters/QueryPriorities.h +++ b/dbms/src/Interpreters/QueryPriorities.h @@ -49,50 +49,36 @@ private: /** If there are higher priority queries - sleep until they are finish or timeout happens. - * Returns true, if higher priority queries has finished at return of function, false, if timout exceeded. */ template - bool waitIfNeed(Priority priority, Duration timeout) + void waitIfNeed(Priority priority, Duration timeout) { if (0 == priority) - return true; - - std::chrono::nanoseconds cur_timeout = timeout; - Stopwatch watch(CLOCK_MONOTONIC_COARSE); + return; std::unique_lock lock(mutex); - while (true) + /// Is there at least one more priority query? + bool found = false; + for (const auto & value : container) { - /// Is there at least one more priority query? - bool found = false; - for (const auto & value : container) + if (value.first >= priority) + break; + + if (value.second > 0) { - if (value.first >= priority) - break; - - if (value.second > 0) - { - found = true; - break; - } - } - - if (!found) - return true; - - CurrentMetrics::Increment metric_increment{CurrentMetrics::QueryPreempted}; - if (std::cv_status::timeout == condvar.wait_for(lock, cur_timeout)) - return false; - else - { - /// False awakening, check and update time limit - auto elapsed = std::chrono::nanoseconds(watch.elapsed()); - if (elapsed >= timeout) - return false; - cur_timeout = timeout - elapsed; + found = true; + break; } } + + if (!found) + return; + + CurrentMetrics::Increment metric_increment{CurrentMetrics::QueryPreempted}; + + /// Spurious wakeups are Ok. We allow to wait less than requested. + condvar.wait_for(lock, timeout); } public: @@ -116,9 +102,9 @@ public: } template - bool waitIfNeed(Duration timeout) + void waitIfNeed(Duration timeout) { - return parent.waitIfNeed(value.first, timeout); + parent.waitIfNeed(value.first, timeout); } }; diff --git a/dbms/src/Interpreters/ReplaceQueryParameterVisitor.cpp b/dbms/src/Interpreters/ReplaceQueryParameterVisitor.cpp new file mode 100644 index 00000000000..325499d59d2 --- /dev/null +++ b/dbms/src/Interpreters/ReplaceQueryParameterVisitor.cpp @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int UNKNOWN_QUERY_PARAMETER; + extern const int BAD_QUERY_PARAMETER; +} + + +void ReplaceQueryParameterVisitor::visit(ASTPtr & ast) +{ + for (auto & child : ast->children) + { + if (child->as()) + visitQueryParameter(child); + else + visit(child); + } +} + +const String & ReplaceQueryParameterVisitor::getParamValue(const String & name) +{ + auto search = query_parameters.find(name); + if (search != query_parameters.end()) + return search->second; + else + throw Exception("Substitution " + backQuote(name) + " is not set", ErrorCodes::UNKNOWN_QUERY_PARAMETER); +} + +void ReplaceQueryParameterVisitor::visitQueryParameter(ASTPtr & ast) +{ + const auto & ast_param = ast->as(); + const String & value = getParamValue(ast_param.name); + const String & type_name = ast_param.type; + + const auto data_type = DataTypeFactory::instance().get(type_name); + auto temp_column_ptr = data_type->createColumn(); + IColumn & temp_column = *temp_column_ptr; + ReadBufferFromString read_buffer{value}; + FormatSettings format_settings; + data_type->deserializeAsWholeText(temp_column, read_buffer, format_settings); + + if (!read_buffer.eof()) + throw Exception("Value " + value + " cannot be parsed as " + type_name + " for query parameter '" + ast_param.name + "'", ErrorCodes::BAD_QUERY_PARAMETER); + + ast = addTypeConversionToAST(std::make_shared(temp_column[0]), type_name); +} + +} diff --git a/dbms/src/Interpreters/ReplaceQueryParameterVisitor.h b/dbms/src/Interpreters/ReplaceQueryParameterVisitor.h new file mode 100644 index 00000000000..1931d4c0ba8 --- /dev/null +++ b/dbms/src/Interpreters/ReplaceQueryParameterVisitor.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +namespace DB +{ + +class ASTQueryParameter; + +/// Visit substitutions in a query, replace ASTQueryParameter with ASTLiteral. +class ReplaceQueryParameterVisitor +{ +public: + ReplaceQueryParameterVisitor(const NameToNameMap & parameters) + : query_parameters(parameters) + {} + + void visit(ASTPtr & ast); + +private: + const NameToNameMap & query_parameters; + const String & getParamValue(const String & name); + void visitQueryParameter(ASTPtr & ast); +}; + +} diff --git a/dbms/src/Interpreters/Set.cpp b/dbms/src/Interpreters/Set.cpp index 98705caa949..7840a314380 100644 --- a/dbms/src/Interpreters/Set.cpp +++ b/dbms/src/Interpreters/Set.cpp @@ -127,9 +127,8 @@ void Set::setHeader(const Block & block) } /// We will insert to the Set only keys, where all components are not NULL. - ColumnPtr null_map_holder; ConstNullMapPtr null_map{}; - extractNestedColumnsAndNullMap(key_columns, null_map_holder, null_map); + ColumnPtr null_map_holder = extractNestedColumnsAndNullMap(key_columns, null_map); if (fill_set_elements) { @@ -168,9 +167,8 @@ bool Set::insertFromBlock(const Block & block) size_t rows = block.rows(); /// We will insert to the Set only keys, where all components are not NULL. - ColumnPtr null_map_holder; ConstNullMapPtr null_map{}; - extractNestedColumnsAndNullMap(key_columns, null_map_holder, null_map); + ColumnPtr null_map_holder = extractNestedColumnsAndNullMap(key_columns, null_map); /// Filter to extract distinct values from the block. ColumnUInt8::MutablePtr filter; @@ -349,9 +347,8 @@ ColumnPtr Set::execute(const Block & block, bool negative) const } /// We will check existence in Set only for keys, where all components are not NULL. - ColumnPtr null_map_holder; ConstNullMapPtr null_map{}; - extractNestedColumnsAndNullMap(key_columns, null_map_holder, null_map); + ColumnPtr null_map_holder = extractNestedColumnsAndNullMap(key_columns, null_map); executeOrdinary(key_columns, vec_res, negative, null_map); diff --git a/dbms/src/Interpreters/SetVariants.cpp b/dbms/src/Interpreters/SetVariants.cpp index 57d78d77526..8b5e8fbc984 100644 --- a/dbms/src/Interpreters/SetVariants.cpp +++ b/dbms/src/Interpreters/SetVariants.cpp @@ -73,10 +73,9 @@ typename SetVariantsTemplate::Type SetVariantsTemplate::choose for (const auto & col : key_columns) { - if (col->isColumnNullable()) + if (auto * nullable = checkAndGetColumn(*col)) { - const ColumnNullable & nullable_col = static_cast(*col); - nested_key_columns.push_back(&nullable_col.getNestedColumn()); + nested_key_columns.push_back(&nullable->getNestedColumn()); has_nullable_key = true; } else @@ -157,7 +156,7 @@ typename SetVariantsTemplate::Type SetVariantsTemplate::choose /// If there is single string key, use hash table of it's values. if (keys_size == 1 && (typeid_cast(nested_key_columns[0]) - || (nested_key_columns[0]->isColumnConst() && typeid_cast(&static_cast(nested_key_columns[0])->getDataColumn())))) + || (isColumnConst(*nested_key_columns[0]) && typeid_cast(&static_cast(nested_key_columns[0])->getDataColumn())))) return Type::key_string; if (keys_size == 1 && typeid_cast(nested_key_columns[0])) diff --git a/dbms/src/Interpreters/SetVariants.h b/dbms/src/Interpreters/SetVariants.h index 8b74f3dd09a..1ff63291a06 100644 --- a/dbms/src/Interpreters/SetVariants.h +++ b/dbms/src/Interpreters/SetVariants.h @@ -78,11 +78,10 @@ protected: for (const auto & col : key_columns) { - if (col->isColumnNullable()) + if (auto * nullable = checkAndGetColumn(*col)) { - const auto & nullable_col = static_cast(*col); - actual_columns.push_back(&nullable_col.getNestedColumn()); - null_maps.push_back(&nullable_col.getNullMapColumn()); + actual_columns.push_back(&nullable->getNestedColumn()); + null_maps.push_back(&nullable->getNullMapColumn()); } else { diff --git a/dbms/src/Interpreters/SyntaxAnalyzer.cpp b/dbms/src/Interpreters/SyntaxAnalyzer.cpp index 71a49b4c106..62982ea1e59 100644 --- a/dbms/src/Interpreters/SyntaxAnalyzer.cpp +++ b/dbms/src/Interpreters/SyntaxAnalyzer.cpp @@ -76,7 +76,9 @@ void collectSourceColumns(const ASTSelectQuery * select_query, StoragePtr storag if (select_query) { const auto & storage_aliases = storage->getColumns().getAliases(); + const auto & storage_virtuals = storage->getColumns().getVirtuals(); source_columns.insert(source_columns.end(), storage_aliases.begin(), storage_aliases.end()); + source_columns.insert(source_columns.end(), storage_virtuals.begin(), storage_virtuals.end()); } } } diff --git a/dbms/src/Interpreters/SystemLog.cpp b/dbms/src/Interpreters/SystemLog.cpp index 94214b26f6e..f46b348db7a 100644 --- a/dbms/src/Interpreters/SystemLog.cpp +++ b/dbms/src/Interpreters/SystemLog.cpp @@ -50,6 +50,12 @@ SystemLogs::SystemLogs(Context & global_context, const Poco::Util::AbstractConfi SystemLogs::~SystemLogs() +{ + shutdown(); +} + + +void SystemLogs::shutdown() { if (query_log) query_log->shutdown(); diff --git a/dbms/src/Interpreters/SystemLog.h b/dbms/src/Interpreters/SystemLog.h index 59dda00e71b..48dbde5a38b 100644 --- a/dbms/src/Interpreters/SystemLog.h +++ b/dbms/src/Interpreters/SystemLog.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -67,6 +68,8 @@ struct SystemLogs SystemLogs(Context & global_context, const Poco::Util::AbstractConfiguration & config); ~SystemLogs(); + void shutdown(); + std::shared_ptr query_log; /// Used to log queries. std::shared_ptr query_thread_log; /// Used to log query threads. std::shared_ptr part_log; /// Used to log operations with parts @@ -101,22 +104,10 @@ public: /** Append a record into log. * Writing to table will be done asynchronously and in case of failure, record could be lost. */ - void add(const LogElement & element) - { - if (is_shutdown) - return; - - /// Without try we could block here in case of queue overflow. - if (!queue.tryPush({false, element})) - LOG_ERROR(log, "SystemLog queue is full"); - } + void add(const LogElement & element); /// Flush data in the buffer to disk - void flush() - { - if (!is_shutdown) - flushImpl(false); - } + void flush(); /// Stop the background flush thread before destructor. No more data will be written. void shutdown(); @@ -130,7 +121,15 @@ protected: const size_t flush_interval_milliseconds; std::atomic is_shutdown{false}; - using QueueItem = std::pair; /// First element is shutdown flag for thread. + enum class EntryType + { + LOG_ELEMENT = 0, + AUTO_FLUSH, + FORCE_FLUSH, + SHUTDOWN, + }; + + using QueueItem = std::pair; /// Queue is bounded. But its size is quite large to not block in all normal cases. ConcurrentBoundedQueue queue {DBMS_SYSTEM_LOG_QUEUE_SIZE}; @@ -140,7 +139,6 @@ protected: * than accumulation of large amount of log records (for example, for query log - processing of large amount of queries). */ std::vector data; - std::mutex data_mutex; Logger * log; @@ -157,7 +155,13 @@ protected: bool is_prepared = false; void prepareTable(); - void flushImpl(bool quiet); + std::mutex flush_mutex; + std::mutex condvar_mutex; + std::condition_variable flush_condvar; + bool force_flushing = false; + + /// flushImpl can be executed only in saving_thread. + void flushImpl(EntryType reason); }; @@ -178,6 +182,37 @@ SystemLog::SystemLog(Context & context_, } +template +void SystemLog::add(const LogElement & element) +{ + if (is_shutdown) + return; + + /// Without try we could block here in case of queue overflow. + if (!queue.tryPush({EntryType::LOG_ELEMENT, element})) + LOG_ERROR(log, "SystemLog queue is full"); +} + + +template +void SystemLog::flush() +{ + if (is_shutdown) + return; + + std::lock_guard flush_lock(flush_mutex); + force_flushing = true; + + /// Tell thread to execute extra flush. + queue.push({EntryType::FORCE_FLUSH, {}}); + + /// Wait for flush being finished. + std::unique_lock lock(condvar_mutex); + while (force_flushing) + flush_condvar.wait(lock); +} + + template void SystemLog::shutdown() { @@ -186,7 +221,7 @@ void SystemLog::shutdown() return; /// Tell thread to shutdown. - queue.push({true, {}}); + queue.push({EntryType::SHUTDOWN, {}}); saving_thread.join(); } @@ -219,16 +254,10 @@ void SystemLog::threadFunction() QueueItem element; bool has_element = false; - bool is_empty; - { - std::unique_lock lock(data_mutex); - is_empty = data.empty(); - } - /// data.size() is increased only in this function /// TODO: get rid of data and queue duality - if (is_empty) + if (data.empty()) { queue.pop(element); has_element = true; @@ -242,25 +271,27 @@ void SystemLog::threadFunction() if (has_element) { - if (element.first) + if (element.first == EntryType::SHUTDOWN) { - /// Shutdown. /// NOTE: MergeTree engine can write data even it is already in shutdown state. - flush(); + flushImpl(element.first); break; } - else + else if (element.first == EntryType::FORCE_FLUSH) { - std::unique_lock lock(data_mutex); - data.push_back(element.second); + flushImpl(element.first); + time_after_last_write.restart(); + continue; } + else + data.push_back(element.second); } size_t milliseconds_elapsed = time_after_last_write.elapsed() / 1000000; if (milliseconds_elapsed >= flush_interval_milliseconds) { /// Write data to a table. - flushImpl(true); + flushImpl(EntryType::AUTO_FLUSH); time_after_last_write.restart(); } } @@ -275,13 +306,11 @@ void SystemLog::threadFunction() template -void SystemLog::flushImpl(bool quiet) +void SystemLog::flushImpl(EntryType reason) { - std::unique_lock lock(data_mutex); - try { - if (quiet && data.empty()) + if ((reason == EntryType::AUTO_FLUSH || reason == EntryType::SHUTDOWN) && data.empty()) return; LOG_TRACE(log, "Flushing system log"); @@ -320,6 +349,12 @@ void SystemLog::flushImpl(bool quiet) /// In case of exception, also clean accumulated data - to avoid locking. data.clear(); } + if (reason == EntryType::FORCE_FLUSH) + { + std::lock_guard lock(condvar_mutex); + force_flushing = false; + flush_condvar.notify_one(); + } } diff --git a/dbms/src/Interpreters/ThreadStatusExt.cpp b/dbms/src/Interpreters/ThreadStatusExt.cpp index 4af414d1eef..757436edfb7 100644 --- a/dbms/src/Interpreters/ThreadStatusExt.cpp +++ b/dbms/src/Interpreters/ThreadStatusExt.cpp @@ -6,6 +6,13 @@ #include #include +#if defined(__linux__) +#include +#include + +#include +#endif + /// Implement some methods of ThreadStatus and CurrentThread here to avoid extra linking dependencies in clickhouse_common_io /// TODO It doesn't make sense. @@ -13,6 +20,12 @@ namespace DB { +namespace ErrorCodes +{ + extern const int CANNOT_SET_THREAD_PRIORITY; +} + + void ThreadStatus::attachQueryContext(Context & query_context_) { query_context = &query_context_; @@ -30,7 +43,7 @@ void ThreadStatus::attachQueryContext(Context & query_context_) } } -const std::string & ThreadStatus::getQueryId() const +StringRef ThreadStatus::getQueryId() const { return query_id; } @@ -39,8 +52,7 @@ void CurrentThread::defaultThreadDeleter() { if (unlikely(!current_thread)) return; - ThreadStatus & thread = CurrentThread::get(); - thread.detachQuery(true, true); + current_thread->detachQuery(true, true); } void ThreadStatus::initializeQuery() @@ -94,6 +106,23 @@ void ThreadStatus::attachQuery(const ThreadGroupStatusPtr & thread_group_, bool thread_group->thread_numbers.emplace_back(thread_number); } +#if defined(__linux__) + /// Set "nice" value if required. + if (query_context) + { + Int32 new_os_thread_priority = query_context->getSettingsRef().os_thread_priority; + if (new_os_thread_priority && hasLinuxCapability(CAP_SYS_NICE)) + { + LOG_TRACE(log, "Setting nice to " << new_os_thread_priority); + + if (0 != setpriority(PRIO_PROCESS, os_thread_id, new_os_thread_priority)) + throwFromErrno("Cannot 'setpriority'", ErrorCodes::CANNOT_SET_THREAD_PRIORITY); + + os_thread_priority = new_os_thread_priority; + } + } +#endif + initPerformanceCounters(); thread_state = ThreadState::AttachedToQuery; } @@ -144,6 +173,18 @@ void ThreadStatus::detachQuery(bool exit_if_already_detached, bool thread_exits) thread_group.reset(); thread_state = thread_exits ? ThreadState::Died : ThreadState::DetachedFromQuery; + +#if defined(__linux__) + if (os_thread_priority) + { + LOG_TRACE(log, "Resetting nice"); + + if (0 != setpriority(PRIO_PROCESS, os_thread_id, 0)) + LOG_ERROR(log, "Cannot 'setpriority' back to zero: " << errnoToString(ErrorCodes::CANNOT_SET_THREAD_PRIORITY, errno)); + + os_thread_priority = 0; + } +#endif } void ThreadStatus::logToQueryThreadLog(QueryThreadLog & thread_log) @@ -197,62 +238,59 @@ void CurrentThread::initializeQuery() { if (unlikely(!current_thread)) return; - get().initializeQuery(); - get().deleter = CurrentThread::defaultThreadDeleter; + current_thread->initializeQuery(); + current_thread->deleter = CurrentThread::defaultThreadDeleter; } void CurrentThread::attachTo(const ThreadGroupStatusPtr & thread_group) { if (unlikely(!current_thread)) return; - get().attachQuery(thread_group, true); - get().deleter = CurrentThread::defaultThreadDeleter; + current_thread->attachQuery(thread_group, true); + current_thread->deleter = CurrentThread::defaultThreadDeleter; } void CurrentThread::attachToIfDetached(const ThreadGroupStatusPtr & thread_group) { if (unlikely(!current_thread)) return; - get().attachQuery(thread_group, false); - get().deleter = CurrentThread::defaultThreadDeleter; + current_thread->attachQuery(thread_group, false); + current_thread->deleter = CurrentThread::defaultThreadDeleter; } -const std::string & CurrentThread::getQueryId() +StringRef CurrentThread::getQueryId() { if (unlikely(!current_thread)) - { - const static std::string empty; - return empty; - } - return get().getQueryId(); + return {}; + return current_thread->getQueryId(); } void CurrentThread::attachQueryContext(Context & query_context) { if (unlikely(!current_thread)) return; - return get().attachQueryContext(query_context); + return current_thread->attachQueryContext(query_context); } void CurrentThread::finalizePerformanceCounters() { if (unlikely(!current_thread)) return; - get().finalizePerformanceCounters(); + current_thread->finalizePerformanceCounters(); } void CurrentThread::detachQuery() { if (unlikely(!current_thread)) return; - get().detachQuery(false); + current_thread->detachQuery(false); } void CurrentThread::detachQueryIfNotDetached() { if (unlikely(!current_thread)) return; - get().detachQuery(true); + current_thread->detachQuery(true); } diff --git a/dbms/src/Interpreters/Users.cpp b/dbms/src/Interpreters/Users.cpp index 930c36ee843..1f5a474d6f1 100644 --- a/dbms/src/Interpreters/Users.cpp +++ b/dbms/src/Interpreters/Users.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/dbms/src/Interpreters/addTypeConversionToAST.cpp b/dbms/src/Interpreters/addTypeConversionToAST.cpp new file mode 100644 index 00000000000..699c3bd27c3 --- /dev/null +++ b/dbms/src/Interpreters/addTypeConversionToAST.cpp @@ -0,0 +1,26 @@ +#include "addTypeConversionToAST.h" + +#include +#include +#include +#include + + +namespace DB +{ + +ASTPtr addTypeConversionToAST(ASTPtr && ast, const String & type_name) +{ + auto func = makeASTFunction("CAST", ast, std::make_shared(type_name)); + + if (ASTWithAlias * ast_with_alias = dynamic_cast(ast.get())) + { + func->alias = ast_with_alias->alias; + func->prefer_alias_to_column_name = ast_with_alias->prefer_alias_to_column_name; + ast_with_alias->alias.clear(); + } + + return func; +} + +} diff --git a/dbms/src/Interpreters/addTypeConversionToAST.h b/dbms/src/Interpreters/addTypeConversionToAST.h new file mode 100644 index 00000000000..56c3a636f45 --- /dev/null +++ b/dbms/src/Interpreters/addTypeConversionToAST.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + + +namespace DB +{ + +/// It will produce an expression with CAST to get an AST with the required type. +ASTPtr addTypeConversionToAST(ASTPtr && ast, const String & type_name); + +} diff --git a/dbms/src/Interpreters/createBlockSelector.cpp b/dbms/src/Interpreters/createBlockSelector.cpp index 192e559cbb1..9db1b435edb 100644 --- a/dbms/src/Interpreters/createBlockSelector.cpp +++ b/dbms/src/Interpreters/createBlockSelector.cpp @@ -30,7 +30,7 @@ IColumn::Selector createBlockSelector( using UnsignedT = std::make_unsigned_t; /// const columns contain only one value, therefore we do not need to read it at every iteration - if (column.isColumnConst()) + if (isColumnConst(column)) { const auto data = static_cast(column).getValue(); const auto shard_num = slots[static_cast(data) % total_weight]; diff --git a/dbms/src/Interpreters/evaluateConstantExpression.cpp b/dbms/src/Interpreters/evaluateConstantExpression.cpp index 7fe92b6d907..1d809078cdb 100644 --- a/dbms/src/Interpreters/evaluateConstantExpression.cpp +++ b/dbms/src/Interpreters/evaluateConstantExpression.cpp @@ -50,7 +50,7 @@ std::pair> evaluateConstantExpression(co const ColumnWithTypeAndName & result = block_with_constants.getByName(name); const IColumn & result_column = *result.column; - if (!result_column.isColumnConst()) + if (!isColumnConst(result_column)) throw Exception("Element of set in IN, VALUES or LIMIT is not a constant expression: " + name, ErrorCodes::BAD_ARGUMENTS); return std::make_pair(result_column[0], result.type); diff --git a/dbms/src/Interpreters/executeQuery.cpp b/dbms/src/Interpreters/executeQuery.cpp index 2e6062f4c19..b001c9bcb0a 100644 --- a/dbms/src/Interpreters/executeQuery.cpp +++ b/dbms/src/Interpreters/executeQuery.cpp @@ -26,9 +26,13 @@ #include #include #include +#include #include -#include "DNSCacheUpdater.h" +#include +#include +#include +#include namespace DB { @@ -150,7 +154,7 @@ static std::tuple executeQueryImpl( { time_t current_time = time(nullptr); - context.setQueryContext(context); + context.makeQueryContext(); CurrentThread::attachQueryContext(context); const Settings & settings = context.getSettingsRef(); @@ -180,7 +184,9 @@ static std::tuple executeQueryImpl( insert_query->has_tail = has_query_tail; } else + { query_end = end; + } } catch (...) { @@ -197,9 +203,20 @@ static std::tuple executeQueryImpl( /// Copy query into string. It will be written to log and presented in processlist. If an INSERT query, string will not include data to insertion. String query(begin, query_end); BlockIO res; + QueryPipeline & pipeline = res.pipeline; try { + /// Replace ASTQueryParameter with ASTLiteral for prepared statements. + if (context.hasQueryParameters()) + { + ReplaceQueryParameterVisitor visitor(context.getQueryParameters()); + visitor.visit(ast); + + /// Get new query after substitutions. + query = serializeAST(*ast); + } + logQuery(query.substr(0, settings.log_queries_cut_to_length), context, internal); /// Check the limits. @@ -222,7 +239,13 @@ static std::tuple executeQueryImpl( context.initializeExternalTablesIfSet(); auto interpreter = InterpreterFactory::get(ast, context, stage); - res = interpreter->execute(); + bool use_processors = settings.experimental_use_processors && interpreter->canExecuteWithProcessors(); + + if (use_processors) + pipeline = interpreter->executeWithProcessors(); + else + res = interpreter->execute(); + if (auto * insert_interpreter = typeid_cast(&*interpreter)) context.setInsertionTable(insert_interpreter->getDatabaseTable()); @@ -232,36 +255,57 @@ static std::tuple executeQueryImpl( if ((*process_list_entry)->isKilled()) throw Exception("Query '" + (*process_list_entry)->getInfo().client_info.current_query_id + "' is killed in pending state", ErrorCodes::QUERY_WAS_CANCELLED); - else + else if (!use_processors) (*process_list_entry)->setQueryStreams(res); } /// Hold element of process list till end of query execution. res.process_list_entry = process_list_entry; - if (res.in) + IBlockInputStream::LocalLimits limits; + limits.mode = IBlockInputStream::LIMITS_CURRENT; + limits.size_limits = SizeLimits(settings.max_result_rows, settings.max_result_bytes, settings.result_overflow_mode); + + if (use_processors) { - res.in->setProgressCallback(context.getProgressCallback()); - res.in->setProcessListElement(context.getProcessListElement()); + pipeline.setProgressCallback(context.getProgressCallback()); + pipeline.setProcessListElement(context.getProcessListElement()); /// Limits on the result, the quota on the result, and also callback for progress. /// Limits apply only to the final result. if (stage == QueryProcessingStage::Complete) { - IBlockInputStream::LocalLimits limits; - limits.mode = IBlockInputStream::LIMITS_CURRENT; - limits.size_limits = SizeLimits(settings.max_result_rows, settings.max_result_bytes, settings.result_overflow_mode); - - res.in->setLimits(limits); - res.in->setQuota(quota); + pipeline.resize(1); + pipeline.addSimpleTransform([&](const Block & header) + { + auto transform = std::make_shared(header, limits); + transform->setQuota(quota); + return transform; + }); } } - - if (res.out) + else { - if (auto stream = dynamic_cast(res.out.get())) + if (res.in) { - stream->setProcessListElement(context.getProcessListElement()); + res.in->setProgressCallback(context.getProgressCallback()); + res.in->setProcessListElement(context.getProcessListElement()); + + /// Limits on the result, the quota on the result, and also callback for progress. + /// Limits apply only to the final result. + if (stage == QueryProcessingStage::Complete) + { + res.in->setLimits(limits); + res.in->setQuota(quota); + } + } + + if (res.out) + { + if (auto stream = dynamic_cast(res.out.get())) + { + stream->setProcessListElement(context.getProcessListElement()); + } } } @@ -291,7 +335,7 @@ static std::tuple executeQueryImpl( } /// Also make possible for caller to log successful query finish and exception during execution. - res.finish_callback = [elem, &context, log_queries] (IBlockInputStream * stream_in, IBlockOutputStream * stream_out) mutable + auto finish_callback = [elem, &context, log_queries] (IBlockInputStream * stream_in, IBlockOutputStream * stream_out) mutable { QueryStatus * process_list_elem = context.getProcessListElement(); @@ -360,7 +404,7 @@ static std::tuple executeQueryImpl( } }; - res.exception_callback = [elem, &context, log_queries] () mutable + auto exception_callback = [elem, &context, log_queries] () mutable { context.getQuota().addError(); @@ -403,6 +447,9 @@ static std::tuple executeQueryImpl( } }; + res.finish_callback = std::move(finish_callback); + res.exception_callback = std::move(exception_callback); + if (!internal && res.in) { std::stringstream log_str; @@ -417,8 +464,6 @@ static std::tuple executeQueryImpl( if (!internal) onExceptionBeforeStart(query, context, current_time); - DNSCacheUpdater::incrementNetworkErrorEventsIfNeeded(); - throw; } @@ -487,6 +532,8 @@ void executeQuery( std::tie(ast, streams) = executeQueryImpl(begin, end, context, false, QueryProcessingStage::Complete, may_have_tail); + auto & pipeline = streams.pipeline; + try { if (streams.out) @@ -540,6 +587,63 @@ void executeQuery( copyData(*streams.in, *out); } + + if (pipeline.initialized()) + { + const ASTQueryWithOutput * ast_query_with_output = dynamic_cast(ast.get()); + + WriteBuffer * out_buf = &ostr; + std::optional out_file_buf; + if (ast_query_with_output && ast_query_with_output->out_file) + { + if (!allow_into_outfile) + throw Exception("INTO OUTFILE is not allowed", ErrorCodes::INTO_OUTFILE_NOT_ALLOWED); + + const auto & out_file = typeid_cast(*ast_query_with_output->out_file).value.safeGet(); + out_file_buf.emplace(out_file, DBMS_DEFAULT_BUFFER_SIZE, O_WRONLY | O_EXCL | O_CREAT); + out_buf = &*out_file_buf; + } + + String format_name = ast_query_with_output && (ast_query_with_output->format != nullptr) + ? *getIdentifierName(ast_query_with_output->format) + : context.getDefaultFormat(); + + if (ast_query_with_output && ast_query_with_output->settings_ast) + InterpreterSetQuery(ast_query_with_output->settings_ast, context).executeForCurrentContext(); + + pipeline.addSimpleTransform([](const Block & header) + { + return std::make_shared(header); + }); + + auto out = context.getOutputFormatProcessor(format_name, *out_buf, pipeline.getHeader()); + + /// Save previous progress callback if any. TODO Do it more conveniently. + auto previous_progress_callback = context.getProgressCallback(); + + /// NOTE Progress callback takes shared ownership of 'out'. + pipeline.setProgressCallback([out, previous_progress_callback] (const Progress & progress) + { + if (previous_progress_callback) + previous_progress_callback(progress); + out->onProgress(progress); + }); + + if (set_content_type) + set_content_type(out->getContentType()); + + if (set_query_id) + set_query_id(context.getClientInfo().current_query_id); + + pipeline.setOutput(std::move(out)); + + { + auto executor = pipeline.execute(); + executor->execute(context.getSettingsRef().max_threads); + } + + pipeline.finalize(); + } } catch (...) { diff --git a/dbms/src/Interpreters/executeQuery.h b/dbms/src/Interpreters/executeQuery.h index d43ca57af10..afb1829fdf0 100644 --- a/dbms/src/Interpreters/executeQuery.h +++ b/dbms/src/Interpreters/executeQuery.h @@ -3,6 +3,7 @@ #include #include +#include namespace DB { @@ -45,4 +46,13 @@ BlockIO executeQuery( bool may_have_embedded_data = false /// If insert query may have embedded data ); + +QueryPipeline executeQueryWithProcessors( + const String & query, /// Query text without INSERT data. The latter must be written to BlockIO::out. + Context & context, /// DB, tables, data types, storage engines, functions, aggregate functions... + bool internal = false, /// If true, this query is caused by another query and thus needn't be registered in the ProcessList. + QueryProcessingStage::Enum stage = QueryProcessingStage::Complete, /// To which stage the query must be executed. + bool may_have_embedded_data = false /// If insert query may have embedded data +); + } diff --git a/dbms/src/Interpreters/joinDispatch.h b/dbms/src/Interpreters/joinDispatch.h new file mode 100644 index 00000000000..438641590d2 --- /dev/null +++ b/dbms/src/Interpreters/joinDispatch.h @@ -0,0 +1,113 @@ +#pragma once + +#include +#include + +#include + + +/** Used in implementation of Join to process different data structures. + */ + +namespace DB +{ + +template +struct MapGetterImpl; + +template <> +struct MapGetterImpl +{ + using Map = Join::MapsAny; +}; + +template <> +struct MapGetterImpl +{ + using Map = Join::MapsAnyFull; +}; + +template <> +struct MapGetterImpl +{ + using Map = Join::MapsAll; +}; + +template <> +struct MapGetterImpl +{ + using Map = Join::MapsAllFull; +}; + +template +struct MapGetterImpl +{ + using Map = Join::MapsAsof; +}; + +template +struct KindTrait +{ + // Affects the Adder trait so that when the right part is empty, adding a default value on the left + static constexpr bool fill_left = static_in_v; + + // Affects the Map trait so that a `used` flag is attached to map slots in order to + // generate default values on the right when the left part is empty + static constexpr bool fill_right = static_in_v; +}; + +template +using Map = typename MapGetterImpl::fill_right, strictness>::Map; + +static constexpr std::array STRICTNESSES = { + ASTTableJoin::Strictness::Any, + ASTTableJoin::Strictness::All, + ASTTableJoin::Strictness::Asof +}; + +static constexpr std::array KINDS = { + ASTTableJoin::Kind::Left, + ASTTableJoin::Kind::Inner, + ASTTableJoin::Kind::Full, + ASTTableJoin::Kind::Right +}; + +/// Init specified join map +inline bool joinDispatchInit(ASTTableJoin::Kind kind, ASTTableJoin::Strictness strictness, Join::MapsVariant & maps) +{ + return static_for<0, KINDS.size() * STRICTNESSES.size()>([&](auto ij) + { + constexpr auto i = ij / STRICTNESSES.size(); + constexpr auto j = ij % STRICTNESSES.size(); + if (kind == KINDS[i] && strictness == STRICTNESSES[j]) + { + maps = Map(); + return true; + } + return false; + }); +} + +/// Call function on specified join map +template +inline bool joinDispatch(ASTTableJoin::Kind kind, ASTTableJoin::Strictness strictness, MapsVariant & maps, Func && func) +{ + return static_for<0, KINDS.size() * STRICTNESSES.size()>([&](auto ij) + { + // NOTE: Avoid using nested static loop as GCC and CLANG have bugs in different ways + // See https://stackoverflow.com/questions/44386415/gcc-and-clang-disagree-about-c17-constexpr-lambda-captures + constexpr auto i = ij / STRICTNESSES.size(); + constexpr auto j = ij % STRICTNESSES.size(); + if (kind == KINDS[i] && strictness == STRICTNESSES[j]) + { + func( + std::integral_constant(), + std::integral_constant(), + std::get>(maps)); + return true; + } + return false; + }); +} + +} diff --git a/dbms/src/Interpreters/tests/CMakeLists.txt b/dbms/src/Interpreters/tests/CMakeLists.txt index 3de6c321de2..d83c5975c08 100644 --- a/dbms/src/Interpreters/tests/CMakeLists.txt +++ b/dbms/src/Interpreters/tests/CMakeLists.txt @@ -12,11 +12,11 @@ target_link_libraries (aggregate PRIVATE dbms) add_executable (hash_map hash_map.cpp) target_include_directories (hash_map SYSTEM BEFORE PRIVATE ${SPARCEHASH_INCLUDE_DIR}) -target_link_libraries (hash_map PRIVATE dbms clickhouse_compression) +target_link_libraries (hash_map PRIVATE dbms) add_executable (hash_map_lookup hash_map_lookup.cpp) target_include_directories (hash_map_lookup SYSTEM BEFORE PRIVATE ${SPARCEHASH_INCLUDE_DIR}) -target_link_libraries (hash_map_lookup PRIVATE dbms clickhouse_compression) +target_link_libraries (hash_map_lookup PRIVATE dbms) add_executable (hash_map3 hash_map3.cpp) target_include_directories(hash_map3 SYSTEM BEFORE PRIVATE ${METROHASH_INCLUDE_DIR}) @@ -24,22 +24,22 @@ target_link_libraries (hash_map3 PRIVATE dbms ${FARMHASH_LIBRARIES} ${METROHASH_ add_executable (hash_map_string hash_map_string.cpp) target_include_directories (hash_map_string SYSTEM BEFORE PRIVATE ${SPARCEHASH_INCLUDE_DIR}) -target_link_libraries (hash_map_string PRIVATE dbms clickhouse_compression) +target_link_libraries (hash_map_string PRIVATE dbms) add_executable (hash_map_string_2 hash_map_string_2.cpp) -target_link_libraries (hash_map_string_2 PRIVATE dbms clickhouse_compression) +target_link_libraries (hash_map_string_2 PRIVATE dbms) add_executable (hash_map_string_3 hash_map_string_3.cpp) target_include_directories(hash_map_string_3 SYSTEM BEFORE PRIVATE ${METROHASH_INCLUDE_DIR}) -target_link_libraries (hash_map_string_3 PRIVATE dbms clickhouse_compression ${FARMHASH_LIBRARIES} ${METROHASH_LIBRARIES}) +target_link_libraries (hash_map_string_3 PRIVATE dbms ${FARMHASH_LIBRARIES} ${METROHASH_LIBRARIES}) add_executable (hash_map_string_small hash_map_string_small.cpp) target_include_directories (hash_map_string_small SYSTEM BEFORE PRIVATE ${SPARCEHASH_INCLUDE_DIR}) -target_link_libraries (hash_map_string_small PRIVATE dbms clickhouse_compression) +target_link_libraries (hash_map_string_small PRIVATE dbms) add_executable (two_level_hash_map two_level_hash_map.cpp) target_include_directories (two_level_hash_map SYSTEM BEFORE PRIVATE ${SPARCEHASH_INCLUDE_DIR}) -target_link_libraries (two_level_hash_map PRIVATE dbms clickhouse_compression) +target_link_libraries (two_level_hash_map PRIVATE dbms) add_executable (compiler_test compiler_test.cpp) target_link_libraries (compiler_test PRIVATE dbms) diff --git a/dbms/src/Interpreters/tests/create_query.cpp b/dbms/src/Interpreters/tests/create_query.cpp index b49a87c6945..11f01ef3a6a 100644 --- a/dbms/src/Interpreters/tests/create_query.cpp +++ b/dbms/src/Interpreters/tests/create_query.cpp @@ -79,6 +79,7 @@ try ASTPtr ast = parseQuery(parser, input.data(), input.data() + input.size(), "", 0); Context context = Context::createGlobal(); + context.makeGlobalContext(); context.setPath("./"); auto database = std::make_shared("test", "./metadata/test/", context); diff --git a/dbms/src/Interpreters/tests/expression.cpp b/dbms/src/Interpreters/tests/expression.cpp index 73502d9067e..2dbf01d148b 100644 --- a/dbms/src/Interpreters/tests/expression.cpp +++ b/dbms/src/Interpreters/tests/expression.cpp @@ -47,6 +47,7 @@ int main(int argc, char ** argv) std::cerr << std::endl; Context context = Context::createGlobal(); + context.makeGlobalContext(); NamesAndTypesList columns { {"x", std::make_shared()}, diff --git a/dbms/src/Interpreters/tests/expression_analyzer.cpp b/dbms/src/Interpreters/tests/expression_analyzer.cpp index 3732e7dce72..079a22620bc 100644 --- a/dbms/src/Interpreters/tests/expression_analyzer.cpp +++ b/dbms/src/Interpreters/tests/expression_analyzer.cpp @@ -97,6 +97,7 @@ int main() }; Context context = Context::createGlobal(); + context.makeGlobalContext(); auto system_database = std::make_shared("system"); context.addDatabase("system", system_database); diff --git a/dbms/src/Interpreters/tests/hash_map_string.cpp b/dbms/src/Interpreters/tests/hash_map_string.cpp index 9076a1e582e..cad701b49ca 100644 --- a/dbms/src/Interpreters/tests/hash_map_string.cpp +++ b/dbms/src/Interpreters/tests/hash_map_string.cpp @@ -277,7 +277,7 @@ struct Grower : public HashTableGrower<> } /// Set the buffer size by the number of elements in the hash table. Used when deserializing a hash table. - void set(size_t /*num_elems*/) + [[noreturn]] void set(size_t /*num_elems*/) { throw Poco::Exception(__PRETTY_FUNCTION__); } diff --git a/dbms/src/Interpreters/tests/in_join_subqueries_preprocessor.cpp b/dbms/src/Interpreters/tests/in_join_subqueries_preprocessor.cpp index ecb21c58831..7c90769b37b 100644 --- a/dbms/src/Interpreters/tests/in_join_subqueries_preprocessor.cpp +++ b/dbms/src/Interpreters/tests/in_join_subqueries_preprocessor.cpp @@ -38,6 +38,7 @@ public: std::string getRemoteTableName() const { return remote_table; } std::string getTableName() const override { return ""; } + std::string getDatabaseName() const override { return ""; } protected: StorageDistributedFake(const std::string & remote_database_, const std::string & remote_table_, size_t shard_count_) @@ -1158,6 +1159,7 @@ bool run() TestResult check(const TestEntry & entry) { static DB::Context context = DB::Context::createGlobal(); + context.makeGlobalContext(); try { diff --git a/dbms/src/Interpreters/tests/select_query.cpp b/dbms/src/Interpreters/tests/select_query.cpp index 951d8e0723a..7267c408999 100644 --- a/dbms/src/Interpreters/tests/select_query.cpp +++ b/dbms/src/Interpreters/tests/select_query.cpp @@ -31,6 +31,7 @@ try DateLUT::instance(); Context context = Context::createGlobal(); + context.makeGlobalContext(); context.setPath("./"); diff --git a/dbms/src/Parsers/ASTAlterQuery.cpp b/dbms/src/Parsers/ASTAlterQuery.cpp index e614f64d208..c7cd100b415 100644 --- a/dbms/src/Parsers/ASTAlterQuery.cpp +++ b/dbms/src/Parsers/ASTAlterQuery.cpp @@ -82,6 +82,13 @@ void ASTAlterCommand::formatImpl( settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str << "MODIFY COLUMN " << (if_exists ? "IF EXISTS " : "") << (settings.hilite ? hilite_none : ""); col_decl->formatImpl(settings, state, frame); } + else if (type == ASTAlterCommand::COMMENT_COLUMN) + { + settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str << "COMMENT COLUMN " << (if_exists ? "IF EXISTS " : "") << (settings.hilite ? hilite_none : ""); + column->formatImpl(settings, state, frame); + settings.ostr << " " << (settings.hilite ? hilite_none : ""); + comment->formatImpl(settings, state, frame); + } else if (type == ASTAlterCommand::MODIFY_ORDER_BY) { settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str << "MODIFY ORDER BY " << (settings.hilite ? hilite_none : ""); @@ -172,13 +179,6 @@ void ASTAlterCommand::formatImpl( settings.ostr << (settings.hilite ? hilite_keyword : "") << " WHERE " << (settings.hilite ? hilite_none : ""); predicate->formatImpl(settings, state, frame); } - else if (type == ASTAlterCommand::COMMENT_COLUMN) - { - settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str << "COMMENT COLUMN " << (settings.hilite ? hilite_none : ""); - column->formatImpl(settings, state, frame); - settings.ostr << " " << (settings.hilite ? hilite_none : ""); - comment->formatImpl(settings, state, frame); - } else if (type == ASTAlterCommand::MODIFY_TTL) { settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str << "MODIFY TTL " << (settings.hilite ? hilite_none : ""); diff --git a/dbms/src/Parsers/ASTCheckQuery.h b/dbms/src/Parsers/ASTCheckQuery.h index 595b6c2ecb6..40665f6f2b6 100644 --- a/dbms/src/Parsers/ASTCheckQuery.h +++ b/dbms/src/Parsers/ASTCheckQuery.h @@ -1,12 +1,17 @@ #pragma once #include +#include + namespace DB { struct ASTCheckQuery : public ASTQueryWithTableAndOutput { + + ASTPtr partition; + /** Get the text that identifies this element. */ String getID(char delim) const override { return "CheckQuery" + (delim + database) + delim + table; } @@ -19,7 +24,7 @@ struct ASTCheckQuery : public ASTQueryWithTableAndOutput } protected: - void formatQueryImpl(const FormatSettings & settings, FormatState &, FormatStateStacked frame) const override + void formatQueryImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override { std::string nl_or_nothing = settings.one_line ? "" : "\n"; @@ -37,6 +42,12 @@ protected: } settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str << backQuoteIfNeed(table) << (settings.hilite ? hilite_none : ""); } + + if (partition) + { + settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str << " PARTITION " << (settings.hilite ? hilite_none : ""); + partition->formatImpl(settings, state, frame); + } } }; diff --git a/dbms/src/Parsers/ASTColumnDeclaration.cpp b/dbms/src/Parsers/ASTColumnDeclaration.cpp index 892be19c6b5..e718d5c292d 100644 --- a/dbms/src/Parsers/ASTColumnDeclaration.cpp +++ b/dbms/src/Parsers/ASTColumnDeclaration.cpp @@ -21,18 +21,18 @@ ASTPtr ASTColumnDeclaration::clone() const res->children.push_back(res->default_expression); } - if (codec) - { - res->codec = codec->clone(); - res->children.push_back(res->codec); - } - if (comment) { res->comment = comment->clone(); res->children.push_back(res->comment); } + if (codec) + { + res->codec = codec->clone(); + res->children.push_back(res->codec); + } + if (ttl) { res->ttl = ttl->clone(); diff --git a/dbms/src/Parsers/ASTColumnDeclaration.h b/dbms/src/Parsers/ASTColumnDeclaration.h index 311ceb4efbc..ad23e0669bc 100644 --- a/dbms/src/Parsers/ASTColumnDeclaration.h +++ b/dbms/src/Parsers/ASTColumnDeclaration.h @@ -15,8 +15,8 @@ public: ASTPtr type; String default_specifier; ASTPtr default_expression; - ASTPtr codec; ASTPtr comment; + ASTPtr codec; ASTPtr ttl; String getID(char delim) const override { return "ColumnDeclaration" + (delim + name); } diff --git a/dbms/src/Parsers/ASTExplainQuery.h b/dbms/src/Parsers/ASTExplainQuery.h index 5ebd02b85f8..d921ff427ae 100644 --- a/dbms/src/Parsers/ASTExplainQuery.h +++ b/dbms/src/Parsers/ASTExplainQuery.h @@ -26,9 +26,10 @@ public: ASTPtr clone() const override { return std::make_shared(*this); } protected: - void formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override + void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override { - settings.ostr << (settings.hilite ? hilite_keyword : "") << toString(kind) << (settings.hilite ? hilite_none : ""); + settings.ostr << (settings.hilite ? hilite_keyword : "") << toString(kind) << (settings.hilite ? hilite_none : "") << " "; + children.at(0)->formatImpl(settings, state, frame); } private: @@ -38,8 +39,8 @@ private: { switch (kind) { - case ParsedAST: return "ParsedAST"; - case AnalyzedSyntax: return "AnalyzedSyntax"; + case ParsedAST: return "AST"; + case AnalyzedSyntax: return "ANALYZE"; } __builtin_unreachable(); diff --git a/dbms/src/Parsers/ASTFunction.cpp b/dbms/src/Parsers/ASTFunction.cpp index 5c5dbc9ba90..b550c7062d1 100644 --- a/dbms/src/Parsers/ASTFunction.cpp +++ b/dbms/src/Parsers/ASTFunction.cpp @@ -126,6 +126,9 @@ void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, Format { if (0 == strcmp(name.c_str(), func[0])) { + if (frame.need_parens) + settings.ostr << '('; + settings.ostr << (settings.hilite ? hilite_operator : "") << func[1] << (settings.hilite ? hilite_none : ""); /** A particularly stupid case. If we have a unary minus before a literal that is a negative number @@ -138,6 +141,9 @@ void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, Format arguments->formatImpl(settings, state, nested_need_parens); written = true; + + if (frame.need_parens) + settings.ostr << ')'; } } } @@ -209,11 +215,17 @@ void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, Format if (!written && 0 == strcmp(name.c_str(), "arrayElement")) { + if (frame.need_parens) + settings.ostr << '('; + arguments->children[0]->formatImpl(settings, state, nested_need_parens); settings.ostr << (settings.hilite ? hilite_operator : "") << '[' << (settings.hilite ? hilite_none : ""); - arguments->children[1]->formatImpl(settings, state, nested_need_parens); + arguments->children[1]->formatImpl(settings, state, nested_dont_need_parens); settings.ostr << (settings.hilite ? hilite_operator : "") << ']' << (settings.hilite ? hilite_none : ""); written = true; + + if (frame.need_parens) + settings.ostr << ')'; } if (!written && 0 == strcmp(name.c_str(), "tupleElement")) @@ -223,10 +235,16 @@ void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, Format { if (lit->value.getType() == Field::Types::UInt64) { + if (frame.need_parens) + settings.ostr << '('; + arguments->children[0]->formatImpl(settings, state, nested_need_parens); settings.ostr << (settings.hilite ? hilite_operator : "") << "." << (settings.hilite ? hilite_none : ""); - arguments->children[1]->formatImpl(settings, state, nested_need_parens); + arguments->children[1]->formatImpl(settings, state, nested_dont_need_parens); written = true; + + if (frame.need_parens) + settings.ostr << ')'; } } } diff --git a/dbms/src/Parsers/ASTQueryParameter.cpp b/dbms/src/Parsers/ASTQueryParameter.cpp new file mode 100644 index 00000000000..462a08b0447 --- /dev/null +++ b/dbms/src/Parsers/ASTQueryParameter.cpp @@ -0,0 +1,24 @@ +#include +#include + + +namespace DB +{ + +void ASTQueryParameter::formatImplWithoutAlias(const FormatSettings & settings, FormatState &, FormatStateStacked) const +{ + settings.ostr + << (settings.hilite ? hilite_substitution : "") << '{' + << (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(name) + << (settings.hilite ? hilite_substitution : "") << ':' + << (settings.hilite ? hilite_identifier : "") << type + << (settings.hilite ? hilite_substitution : "") << '}' + << (settings.hilite ? hilite_none : ""); +} + +void ASTQueryParameter::appendColumnNameImpl(WriteBuffer & ostr) const +{ + writeString(name, ostr); +} + +} diff --git a/dbms/src/Parsers/ASTQueryParameter.h b/dbms/src/Parsers/ASTQueryParameter.h new file mode 100644 index 00000000000..858b23a0250 --- /dev/null +++ b/dbms/src/Parsers/ASTQueryParameter.h @@ -0,0 +1,29 @@ +#pragma once + +#include + + +namespace DB +{ + +/// Parameter in query with name and type of substitution ({name:type}). +/// Example: SELECT * FROM table WHERE id = {pid:UInt16}. +class ASTQueryParameter : public ASTWithAlias +{ +public: + String name; + String type; + + ASTQueryParameter(const String & name_, const String & type_) : name(name_), type(type_) {} + + /** Get the text that identifies this element. */ + String getID(char delim) const override { return String("QueryParameter") + delim + name + ':' + type; } + + ASTPtr clone() const override { return std::make_shared(*this); } + +protected: + void formatImplWithoutAlias(const FormatSettings & settings, FormatState &, FormatStateStacked) const override; + void appendColumnNameImpl(WriteBuffer & ostr) const override; +}; + +} diff --git a/dbms/src/Parsers/ASTQueryWithTableAndOutput.cpp b/dbms/src/Parsers/ASTQueryWithTableAndOutput.cpp new file mode 100644 index 00000000000..1e16fb6f0ee --- /dev/null +++ b/dbms/src/Parsers/ASTQueryWithTableAndOutput.cpp @@ -0,0 +1,14 @@ +#include + + +namespace DB +{ + +void ASTQueryWithTableAndOutput::formatHelper(const FormatSettings & settings, const char * name) const +{ + settings.ostr << (settings.hilite ? hilite_keyword : "") << name << " " << (settings.hilite ? hilite_none : ""); + settings.ostr << (!database.empty() ? backQuoteIfNeed(database) + "." : "") << backQuoteIfNeed(table); +} + +} + diff --git a/dbms/src/Parsers/ASTQueryWithTableAndOutput.h b/dbms/src/Parsers/ASTQueryWithTableAndOutput.h index 3f3fd036d78..594876ace7b 100644 --- a/dbms/src/Parsers/ASTQueryWithTableAndOutput.h +++ b/dbms/src/Parsers/ASTQueryWithTableAndOutput.h @@ -9,7 +9,7 @@ namespace DB /** Query specifying table name and, possibly, the database and the FORMAT section. - */ + */ class ASTQueryWithTableAndOutput : public ASTQueryWithOutput { public: @@ -18,11 +18,7 @@ public: bool temporary{false}; protected: - void formatHelper(const FormatSettings & settings, const char * name) const - { - settings.ostr << (settings.hilite ? hilite_keyword : "") << name << " " << (settings.hilite ? hilite_none : "") - << (!database.empty() ? backQuoteIfNeed(database) + "." : "") << backQuoteIfNeed(table); - } + void formatHelper(const FormatSettings & settings, const char * name) const; }; @@ -43,7 +39,7 @@ public: protected: void formatQueryImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override { - formatHelper(settings, AstIDAndQueryNames::Query); + formatHelper(settings, temporary ? AstIDAndQueryNames::QueryTemporary : AstIDAndQueryNames::Query); } }; diff --git a/dbms/src/Parsers/ASTShowTablesQuery.cpp b/dbms/src/Parsers/ASTShowTablesQuery.cpp new file mode 100644 index 00000000000..dd7b0d013ad --- /dev/null +++ b/dbms/src/Parsers/ASTShowTablesQuery.cpp @@ -0,0 +1,37 @@ +#include +#include + + +namespace DB +{ + +ASTPtr ASTShowTablesQuery::clone() const +{ + auto res = std::make_shared(*this); + res->children.clear(); + cloneOutputOptions(*res); + return res; +} + +void ASTShowTablesQuery::formatQueryImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const +{ + if (databases) + { + settings.ostr << (settings.hilite ? hilite_keyword : "") << "SHOW DATABASES" << (settings.hilite ? hilite_none : ""); + } + else + { + settings.ostr << (settings.hilite ? hilite_keyword : "") << "SHOW " << (temporary ? "TEMPORARY " : "") << "TABLES" << (settings.hilite ? hilite_none : ""); + + if (!from.empty()) + settings.ostr << (settings.hilite ? hilite_keyword : "") << " FROM " << (settings.hilite ? hilite_none : "") + << backQuoteIfNeed(from); + + if (!like.empty()) + settings.ostr << (settings.hilite ? hilite_keyword : "") << " LIKE " << (settings.hilite ? hilite_none : "") + << std::quoted(like, '\''); + } +} + +} + diff --git a/dbms/src/Parsers/ASTShowTablesQuery.h b/dbms/src/Parsers/ASTShowTablesQuery.h index 58915df0e60..9b994b6e31f 100644 --- a/dbms/src/Parsers/ASTShowTablesQuery.h +++ b/dbms/src/Parsers/ASTShowTablesQuery.h @@ -23,34 +23,10 @@ public: /** Get the text that identifies this element. */ String getID(char) const override { return "ShowTables"; } - ASTPtr clone() const override - { - auto res = std::make_shared(*this); - res->children.clear(); - cloneOutputOptions(*res); - return res; - } + ASTPtr clone() const override; protected: - void formatQueryImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override - { - if (databases) - { - settings.ostr << (settings.hilite ? hilite_keyword : "") << "SHOW DATABASES" << (settings.hilite ? hilite_none : ""); - } - else - { - settings.ostr << (settings.hilite ? hilite_keyword : "") << "SHOW TABLES" << (settings.hilite ? hilite_none : ""); - - if (!from.empty()) - settings.ostr << (settings.hilite ? hilite_keyword : "") << " FROM " << (settings.hilite ? hilite_none : "") - << backQuoteIfNeed(from); - - if (!like.empty()) - settings.ostr << (settings.hilite ? hilite_keyword : "") << " LIKE " << (settings.hilite ? hilite_none : "") - << std::quoted(like, '\''); - } - } + void formatQueryImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override; }; } diff --git a/dbms/src/Parsers/ASTTablesInSelectQuery.cpp b/dbms/src/Parsers/ASTTablesInSelectQuery.cpp index 98cf6254a4f..47be2008284 100644 --- a/dbms/src/Parsers/ASTTablesInSelectQuery.cpp +++ b/dbms/src/Parsers/ASTTablesInSelectQuery.cpp @@ -81,6 +81,7 @@ ASTPtr ASTTablesInSelectQuery::clone() const void ASTTableExpression::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const { + frame.current_select = this; std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' '); if (database_and_table_name) @@ -183,14 +184,14 @@ void ASTTableJoin::formatImplAfterTable(const FormatSettings & settings, FormatS if (using_expression_list) { - settings.ostr << (settings.hilite ? hilite_keyword : "") << "USING " << (settings.hilite ? hilite_none : ""); + settings.ostr << (settings.hilite ? hilite_keyword : "") << " USING " << (settings.hilite ? hilite_none : ""); settings.ostr << "("; using_expression_list->formatImpl(settings, state, frame); settings.ostr << ")"; } else if (on_expression) { - settings.ostr << (settings.hilite ? hilite_keyword : "") << "ON " << (settings.hilite ? hilite_none : ""); + settings.ostr << (settings.hilite ? hilite_keyword : "") << " ON " << (settings.hilite ? hilite_none : ""); on_expression->formatImpl(settings, state, frame); } } @@ -226,7 +227,6 @@ void ASTTablesInSelectQueryElement::formatImpl(const FormatSettings & settings, } table_expression->formatImpl(settings, state, frame); - settings.ostr << " "; if (table_join) table_join->as().formatImplAfterTable(settings, state, frame); diff --git a/dbms/src/Parsers/ASTWithAlias.cpp b/dbms/src/Parsers/ASTWithAlias.cpp index 67a4401f9a5..0239d0b34cd 100644 --- a/dbms/src/Parsers/ASTWithAlias.cpp +++ b/dbms/src/Parsers/ASTWithAlias.cpp @@ -16,27 +16,27 @@ void ASTWithAlias::writeAlias(const String & name, const FormatSettings & settin void ASTWithAlias::formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const { - if (!alias.empty()) + /// If we have previously output this node elsewhere in the query, now it is enough to output only the alias. + /// This is needed because the query can become extraordinary large after substitution of aliases. + if (!alias.empty() && !state.printed_asts_with_alias.emplace(frame.current_select, alias, getTreeHash()).second) { - /// If we have previously output this node elsewhere in the query, now it is enough to output only the alias. - if (!state.printed_asts_with_alias.emplace(frame.current_select, alias).second) - { - settings.writeIdentifier(alias); - return; - } + settings.writeIdentifier(alias); } - - /// If there is an alias, then parentheses are required around the entire expression, including the alias. Because a record of the form `0 AS x + 0` is syntactically invalid. - if (frame.need_parens && !alias.empty()) - settings.ostr <<'('; - - formatImplWithoutAlias(settings, state, frame); - - if (!alias.empty()) + else { - writeAlias(alias, settings); - if (frame.need_parens) - settings.ostr <<')'; + /// If there is an alias, then parentheses are required around the entire expression, including the alias. + /// Because a record of the form `0 AS x + 0` is syntactically invalid. + if (frame.need_parens && !alias.empty()) + settings.ostr << '('; + + formatImplWithoutAlias(settings, state, frame); + + if (!alias.empty()) + { + writeAlias(alias, settings); + if (frame.need_parens) + settings.ostr << ')'; + } } } diff --git a/dbms/src/Parsers/ExpressionElementParsers.cpp b/dbms/src/Parsers/ExpressionElementParsers.cpp index 2741aa0d491..9c0071c64e8 100644 --- a/dbms/src/Parsers/ExpressionElementParsers.cpp +++ b/dbms/src/Parsers/ExpressionElementParsers.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -1199,6 +1200,52 @@ bool ParserQualifiedAsterisk::parseImpl(Pos & pos, ASTPtr & node, Expected & exp } +bool ParserSubstitution::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) +{ + if (pos->type != TokenType::OpeningCurlyBrace) + return false; + + ++pos; + + if (pos->type != TokenType::BareWord) + { + expected.add(pos, "substitution name (identifier)"); + return false; + } + + String name(pos->begin, pos->end); + ++pos; + + if (pos->type != TokenType::Colon) + { + expected.add(pos, "colon between name and type"); + return false; + } + + ++pos; + + auto old_pos = pos; + ParserIdentifierWithOptionalParameters type_parser; + if (!type_parser.ignore(pos, expected)) + { + expected.add(pos, "substitution type"); + return false; + } + + String type(old_pos->begin, pos->begin); + + if (pos->type != TokenType::ClosingCurlyBrace) + { + expected.add(pos, "closing curly brace"); + return false; + } + + ++pos; + node = std::make_shared(name, type); + return true; +} + + bool ParserExpressionElement::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { return ParserSubquery().parse(pos, node, expected) @@ -1218,7 +1265,8 @@ bool ParserExpressionElement::parseImpl(Pos & pos, ASTPtr & node, Expected & exp || ParserFunction().parse(pos, node, expected) || ParserQualifiedAsterisk().parse(pos, node, expected) || ParserAsterisk().parse(pos, node, expected) - || ParserCompoundIdentifier().parse(pos, node, expected); + || ParserCompoundIdentifier().parse(pos, node, expected) + || ParserSubstitution().parse(pos, node, expected); } diff --git a/dbms/src/Parsers/ExpressionElementParsers.h b/dbms/src/Parsers/ExpressionElementParsers.h index e3dc5ae44d0..b4fe77e8bb3 100644 --- a/dbms/src/Parsers/ExpressionElementParsers.h +++ b/dbms/src/Parsers/ExpressionElementParsers.h @@ -242,6 +242,17 @@ private: }; +/** Prepared statements. + * Parse query with parameter expression {name:type}. + */ +class ParserSubstitution : public IParserBase +{ +protected: + const char * getName() const { return "substitution"; } + bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); +}; + + /** The expression element is one of: an expression in parentheses, an array, a literal, a function, an identifier, an asterisk. */ class ParserExpressionElement : public IParserBase diff --git a/dbms/src/Parsers/IAST.cpp b/dbms/src/Parsers/IAST.cpp index c54e8973c60..de19e3639db 100644 --- a/dbms/src/Parsers/IAST.cpp +++ b/dbms/src/Parsers/IAST.cpp @@ -17,12 +17,13 @@ namespace ErrorCodes } -const char * IAST::hilite_keyword = "\033[1m"; -const char * IAST::hilite_identifier = "\033[0;36m"; -const char * IAST::hilite_function = "\033[0;33m"; -const char * IAST::hilite_operator = "\033[1;33m"; -const char * IAST::hilite_alias = "\033[0;32m"; -const char * IAST::hilite_none = "\033[0m"; +const char * IAST::hilite_keyword = "\033[1m"; +const char * IAST::hilite_identifier = "\033[0;36m"; +const char * IAST::hilite_function = "\033[0;33m"; +const char * IAST::hilite_operator = "\033[1;33m"; +const char * IAST::hilite_alias = "\033[0;32m"; +const char * IAST::hilite_substitution = "\033[1;36m"; +const char * IAST::hilite_none = "\033[0m"; String backQuoteIfNeed(const String & x) diff --git a/dbms/src/Parsers/IAST.h b/dbms/src/Parsers/IAST.h index 89ab8fb05c3..a2aa9f2b23e 100644 --- a/dbms/src/Parsers/IAST.h +++ b/dbms/src/Parsers/IAST.h @@ -161,6 +161,13 @@ public: nl_or_ws = one_line ? ' ' : '\n'; } + FormatSettings(std::ostream & ostr_, const FormatSettings & other) + : ostr(ostr_), hilite(other.hilite), one_line(other.one_line), + always_quote_identifiers(other.always_quote_identifiers), identifier_quoting_style(other.identifier_quoting_style) + { + nl_or_ws = one_line ? ' ' : '\n'; + } + void writeIdentifier(const String & name) const; }; @@ -170,7 +177,10 @@ public: /** The SELECT query in which the alias was found; identifier of a node with such an alias. * It is necessary that when the node has met again, output only the alias. */ - std::set> printed_asts_with_alias; + std::set> printed_asts_with_alias; }; /// The state that is copied when each node is formatted. For example, nesting level. @@ -201,6 +211,7 @@ public: static const char * hilite_function; static const char * hilite_operator; static const char * hilite_alias; + static const char * hilite_substitution; static const char * hilite_none; private: diff --git a/dbms/src/Parsers/Lexer.cpp b/dbms/src/Parsers/Lexer.cpp index 0494eacd490..fe56dfadd5b 100644 --- a/dbms/src/Parsers/Lexer.cpp +++ b/dbms/src/Parsers/Lexer.cpp @@ -173,7 +173,10 @@ Token Lexer::nextTokenImpl() return Token(TokenType::OpeningSquareBracket, token_begin, ++pos); case ']': return Token(TokenType::ClosingSquareBracket, token_begin, ++pos); - + case '{': + return Token(TokenType::OpeningCurlyBrace, token_begin, ++pos); + case '}': + return Token(TokenType::ClosingCurlyBrace, token_begin, ++pos); case ',': return Token(TokenType::Comma, token_begin, ++pos); case ';': diff --git a/dbms/src/Parsers/Lexer.h b/dbms/src/Parsers/Lexer.h index 13cd00e3dd3..3f2712bae08 100644 --- a/dbms/src/Parsers/Lexer.h +++ b/dbms/src/Parsers/Lexer.h @@ -23,6 +23,9 @@ namespace DB M(OpeningSquareBracket) \ M(ClosingSquareBracket) \ \ + M(OpeningCurlyBrace) \ + M(ClosingCurlyBrace) \ + \ M(Comma) \ M(Semicolon) \ M(Dot) /** Compound identifiers, like a.b or tuple access operator a.1, (x, y).2. */ \ diff --git a/dbms/src/Parsers/ParserCheckQuery.cpp b/dbms/src/Parsers/ParserCheckQuery.cpp index cd25e60b887..5ba8119571d 100644 --- a/dbms/src/Parsers/ParserCheckQuery.cpp +++ b/dbms/src/Parsers/ParserCheckQuery.cpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace DB @@ -11,9 +12,11 @@ namespace DB bool ParserCheckQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { ParserKeyword s_check_table("CHECK TABLE"); + ParserKeyword s_partition("PARTITION"); ParserToken s_dot(TokenType::Dot); ParserIdentifier table_parser; + ParserPartition partition_parser; ASTPtr table; ASTPtr database; @@ -23,24 +26,28 @@ bool ParserCheckQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) if (!table_parser.parse(pos, database, expected)) return false; + auto query = std::make_shared(); if (s_dot.ignore(pos)) { if (!table_parser.parse(pos, table, expected)) return false; - auto query = std::make_shared(); getIdentifierName(database, query->database); getIdentifierName(table, query->table); - node = query; } else { table = database; - auto query = std::make_shared(); getIdentifierName(table, query->table); - node = query; } + if (s_partition.ignore(pos, expected)) + { + if (!partition_parser.parse(pos, query->partition, expected)) + return false; + } + + node = query; return true; } diff --git a/dbms/src/Parsers/TablePropertiesQueriesASTs.h b/dbms/src/Parsers/TablePropertiesQueriesASTs.h index e68a3b46e4a..f2fa7c506a6 100644 --- a/dbms/src/Parsers/TablePropertiesQueriesASTs.h +++ b/dbms/src/Parsers/TablePropertiesQueriesASTs.h @@ -10,24 +10,28 @@ struct ASTExistsQueryIDAndQueryNames { static constexpr auto ID = "ExistsQuery"; static constexpr auto Query = "EXISTS TABLE"; + static constexpr auto QueryTemporary = "EXISTS TEMPORARY TABLE"; }; struct ASTShowCreateTableQueryIDAndQueryNames { static constexpr auto ID = "ShowCreateTableQuery"; static constexpr auto Query = "SHOW CREATE TABLE"; + static constexpr auto QueryTemporary = "SHOW CREATE TEMPORARY TABLE"; }; struct ASTShowCreateDatabaseQueryIDAndQueryNames { static constexpr auto ID = "ShowCreateDatabaseQuery"; static constexpr auto Query = "SHOW CREATE DATABASE"; + static constexpr auto QueryTemporary = "SHOW CREATE TEMPORARY DATABASE"; }; struct ASTDescribeQueryExistsQueryIDAndQueryNames { static constexpr auto ID = "DescribeQuery"; static constexpr auto Query = "DESCRIBE TABLE"; + static constexpr auto QueryTemporary = "DESCRIBE TEMPORARY TABLE"; }; using ASTExistsQuery = ASTQueryWithTableAndOutputImpl; diff --git a/dbms/src/Parsers/tests/lexer.cpp b/dbms/src/Parsers/tests/lexer.cpp index dca93b469bd..d9135b08c28 100644 --- a/dbms/src/Parsers/tests/lexer.cpp +++ b/dbms/src/Parsers/tests/lexer.cpp @@ -28,6 +28,8 @@ std::map hilite = {TokenType::ClosingRoundBracket, "\033[1;33m"}, {TokenType::OpeningSquareBracket, "\033[1;33m"}, {TokenType::ClosingSquareBracket, "\033[1;33m"}, + {TokenType::OpeningCurlyBrace, "\033[1;33m"}, + {TokenType::ClosingCurlyBrace, "\033[1;33m"}, {TokenType::Comma, "\033[1;33m"}, {TokenType::Semicolon, "\033[1;33m"}, diff --git a/dbms/src/Processors/CMakeLists.txt b/dbms/src/Processors/CMakeLists.txt new file mode 100644 index 00000000000..99ba159eaf4 --- /dev/null +++ b/dbms/src/Processors/CMakeLists.txt @@ -0,0 +1,4 @@ +if (ENABLE_TESTS) + add_subdirectory (tests) +endif () + diff --git a/dbms/src/Processors/Chunk.cpp b/dbms/src/Processors/Chunk.cpp new file mode 100644 index 00000000000..f68502fc4b4 --- /dev/null +++ b/dbms/src/Processors/Chunk.cpp @@ -0,0 +1,155 @@ +#include +#include +#include + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int POSITION_OUT_OF_BOUND; +} + +Chunk::Chunk(DB::Columns columns_, UInt64 num_rows_) : columns(std::move(columns_)), num_rows(num_rows_) +{ + checkNumRowsIsConsistent(); +} + +Chunk::Chunk(Columns columns_, UInt64 num_rows_, ChunkInfoPtr chunk_info_) + : columns(std::move(columns_)), num_rows(num_rows_), chunk_info(std::move(chunk_info_)) +{ + checkNumRowsIsConsistent(); +} + +static Columns unmuteColumns(MutableColumns && mut_columns) +{ + Columns columns; + columns.reserve(mut_columns.size()); + for (auto & col : mut_columns) + columns.emplace_back(std::move(col)); + + return columns; +} + +Chunk::Chunk(MutableColumns columns_, UInt64 num_rows_) + : columns(unmuteColumns(std::move(columns_))), num_rows(num_rows_) +{ +} + +Chunk::Chunk(MutableColumns columns_, UInt64 num_rows_, ChunkInfoPtr chunk_info_) + : columns(unmuteColumns(std::move(columns_))), num_rows(num_rows_), chunk_info(std::move(chunk_info_)) +{ +} + +Chunk Chunk::clone() const +{ + return Chunk(getColumns(), getNumRows()); +} + +void Chunk::setColumns(Columns columns_, UInt64 num_rows_) +{ + columns = std::move(columns_); + num_rows = num_rows_; + checkNumRowsIsConsistent(); +} + +void Chunk::setColumns(MutableColumns columns_, UInt64 num_rows_) +{ + columns = unmuteColumns(std::move(columns_)); + num_rows = num_rows_; + checkNumRowsIsConsistent(); +} + +void Chunk::checkNumRowsIsConsistent() +{ + for (auto & column : columns) + if (column->size() != num_rows) + throw Exception("Invalid number of rows in Chunk column " + column->getName()+ ": expected " + + toString(num_rows) + ", got " + toString(column->size()), ErrorCodes::LOGICAL_ERROR); +} + +MutableColumns Chunk::mutateColumns() +{ + size_t num_columns = columns.size(); + MutableColumns mut_columns(num_columns); + for (size_t i = 0; i < num_columns; ++i) + mut_columns[i] = (*std::move(columns[i])).mutate(); + + columns.clear(); + num_rows = 0; + + return mut_columns; +} + +MutableColumns Chunk::cloneEmptyColumns() const +{ + size_t num_columns = columns.size(); + MutableColumns mut_columns(num_columns); + for (size_t i = 0; i < num_columns; ++i) + mut_columns[i] = columns[i]->cloneEmpty(); + return mut_columns; +} + +Columns Chunk::detachColumns() +{ + num_rows = 0; + return std::move(columns); +} + +void Chunk::erase(size_t position) +{ + if (columns.empty()) + throw Exception("Chunk is empty", ErrorCodes::POSITION_OUT_OF_BOUND); + + if (position >= columns.size()) + throw Exception("Position " + toString(position) + " out of bound in Chunk::erase(), max position = " + + toString(columns.size() - 1), ErrorCodes::POSITION_OUT_OF_BOUND); + + columns.erase(columns.begin() + position); +} + +UInt64 Chunk::bytes() const +{ + UInt64 res = 0; + for (const auto & column : columns) + res += column->byteSize(); + + return res; +} + +UInt64 Chunk::allocatedBytes() const +{ + UInt64 res = 0; + for (const auto & column : columns) + res += column->allocatedBytes(); + + return res; +} + +std::string Chunk::dumpStructure() const +{ + WriteBufferFromOwnString out; + for (auto & column : columns) + out << ' ' << column->dumpStructure(); + + return out.str(); +} + + +void ChunkMissingValues::setBit(size_t column_idx, size_t row_idx) +{ + RowsBitMask & mask = rows_mask_by_column_id[column_idx]; + mask.resize(row_idx + 1); + mask[row_idx] = true; +} + +const ChunkMissingValues::RowsBitMask & ChunkMissingValues::getDefaultsBitmask(size_t column_idx) const +{ + static RowsBitMask none; + auto it = rows_mask_by_column_id.find(column_idx); + if (it != rows_mask_by_column_id.end()) + return it->second; + return none; +} + +} diff --git a/dbms/src/Processors/Chunk.h b/dbms/src/Processors/Chunk.h new file mode 100644 index 00000000000..7e33d8cf1c0 --- /dev/null +++ b/dbms/src/Processors/Chunk.h @@ -0,0 +1,117 @@ +#pragma once + +#include +#include + +namespace DB +{ + +class ChunkInfo +{ +public: + virtual ~ChunkInfo() = default; + ChunkInfo() = default; +}; + +using ChunkInfoPtr = std::shared_ptr; + +class Chunk +{ +public: + Chunk() = default; + Chunk(const Chunk & other) = delete; + Chunk(Chunk && other) noexcept + : columns(std::move(other.columns)) + , num_rows(other.num_rows) + , chunk_info(std::move(other.chunk_info)) + { + other.num_rows = 0; + } + + Chunk(Columns columns_, UInt64 num_rows_); + Chunk(Columns columns_, UInt64 num_rows_, ChunkInfoPtr chunk_info_); + Chunk(MutableColumns columns_, UInt64 num_rows_); + Chunk(MutableColumns columns_, UInt64 num_rows_, ChunkInfoPtr chunk_info_); + + Chunk & operator=(const Chunk & other) = delete; + Chunk & operator=(Chunk && other) noexcept + { + columns = std::move(other.columns); + chunk_info = std::move(other.chunk_info); + num_rows = other.num_rows; + other.num_rows = 0; + return *this; + } + + Chunk clone() const; + + void swap(Chunk & other) + { + columns.swap(other.columns); + chunk_info.swap(other.chunk_info); + std::swap(num_rows, other.num_rows); + } + + void clear() + { + num_rows = 0; + columns.clear(); + chunk_info.reset(); + } + + const Columns & getColumns() const { return columns; } + void setColumns(Columns columns_, UInt64 num_rows_); + void setColumns(MutableColumns columns_, UInt64 num_rows_); + Columns detachColumns(); + MutableColumns mutateColumns(); + /** Get empty columns with the same types as in block. */ + MutableColumns cloneEmptyColumns() const; + + const ChunkInfoPtr & getChunkInfo() const { return chunk_info; } + void setChunkInfo(ChunkInfoPtr chunk_info_) { chunk_info = std::move(chunk_info_); } + + UInt64 getNumRows() const { return num_rows; } + UInt64 getNumColumns() const { return columns.size(); } + bool hasNoRows() const { return num_rows == 0; } + bool hasNoColumns() const { return columns.empty(); } + bool empty() const { return hasNoRows() && hasNoColumns(); } + operator bool() const { return !empty(); } + + void erase(size_t position); + + UInt64 bytes() const; + UInt64 allocatedBytes() const; + + std::string dumpStructure() const; + +private: + Columns columns; + UInt64 num_rows = 0; + ChunkInfoPtr chunk_info; + + void checkNumRowsIsConsistent(); +}; + +using Chunks = std::vector; + +/// Block extension to support delayed defaults. AddingDefaultsProcessor uses it to replace missing values with column defaults. +class ChunkMissingValues : public ChunkInfo +{ +public: + using RowsBitMask = std::vector; /// a bit per row for a column + + const RowsBitMask & getDefaultsBitmask(size_t column_idx) const; + void setBit(size_t column_idx, size_t row_idx); + bool empty() const { return rows_mask_by_column_id.empty(); } + size_t size() const { return rows_mask_by_column_id.size(); } + void clear() { rows_mask_by_column_id.clear(); } + +private: + using RowsMaskByColumnId = std::unordered_map; + + /// If rows_mask_by_column_id[column_id][row_id] is true related value in Block should be replaced with column default. + /// It could contain less columns and rows then related block. + RowsMaskByColumnId rows_mask_by_column_id; +}; + +} diff --git a/dbms/src/Processors/ConcatProcessor.cpp b/dbms/src/Processors/ConcatProcessor.cpp new file mode 100644 index 00000000000..d3333c320c0 --- /dev/null +++ b/dbms/src/Processors/ConcatProcessor.cpp @@ -0,0 +1,63 @@ +#include + + +namespace DB +{ + +ConcatProcessor::Status ConcatProcessor::prepare() +{ + auto & output = outputs.front(); + + /// Check can output. + + if (output.isFinished()) + { + for (; current_input != inputs.end(); ++current_input) + current_input->close(); + + return Status::Finished; + } + + if (!output.isNeeded()) + { + if (current_input != inputs.end()) + current_input->setNotNeeded(); + + return Status::PortFull; + } + + if (!output.canPush()) + return Status::PortFull; + + /// Check can input. + + if (current_input == inputs.end()) + return Status::Finished; + + if (current_input->isFinished()) + { + ++current_input; + if (current_input == inputs.end()) + { + output.finish(); + return Status::Finished; + } + } + + auto & input = *current_input; + + input.setNeeded(); + + if (!input.hasData()) + return Status::NeedData; + + /// Move data. + output.push(input.pull()); + + /// Now, we pushed to output, and it must be full. + return Status::PortFull; +} + +} + + diff --git a/dbms/src/Processors/ConcatProcessor.h b/dbms/src/Processors/ConcatProcessor.h new file mode 100644 index 00000000000..4aa5099b38a --- /dev/null +++ b/dbms/src/Processors/ConcatProcessor.h @@ -0,0 +1,35 @@ +#pragma once + +#include + + +namespace DB +{ + +/** Has arbitary non zero number of inputs and one output. + * All of them have the same structure. + * + * Pulls all data from first input, then all data from second input, etc... + * Doesn't do any heavy calculations. + * Preserves an order of data. + */ +class ConcatProcessor : public IProcessor +{ +public: + ConcatProcessor(const Block & header, size_t num_inputs) + : IProcessor(InputPorts(num_inputs, header), OutputPorts{header}), current_input(inputs.begin()) + { + } + + String getName() const override { return "Concat"; } + + Status prepare() override; + + OutputPort & getOutputPort() { return outputs.front(); } + +private: + InputPorts::iterator current_input; +}; + +} + diff --git a/dbms/src/Processors/Executors/ParallelPipelineExecutor.cpp b/dbms/src/Processors/Executors/ParallelPipelineExecutor.cpp new file mode 100644 index 00000000000..7f0969e6451 --- /dev/null +++ b/dbms/src/Processors/Executors/ParallelPipelineExecutor.cpp @@ -0,0 +1,101 @@ +#include +#include +#include +#include + + +namespace DB +{ +// +//ParallelPipelineExecutor::ParallelPipelineExecutor(const std::vector & processors, ThreadPool & pool) +// : processors(processors), pool(pool) +//{ +//} +// +// +//ParallelPipelineExecutor::Status ParallelPipelineExecutor::prepare() +//{ +// current_processor = nullptr; +// +// bool has_someone_to_wait = false; +// +// for (auto & element : processors) +// { +// traverse(*element, +// [&] (IProcessor & processor) +// { +// { +// std::lock_guard lock(mutex); +// if (active_processors.count(&processor)) +// { +// has_someone_to_wait = true; +// return Status::Wait; +// } +// } +// +// Status status = processor.prepare(); +// +// if (status == Status::Wait) +// has_someone_to_wait = true; +// +// if (status == Status::Ready || status == Status::Async) +// { +// current_processor = &processor; +// current_status = status; +// } +// +// return status; +// }); +// +// if (current_processor) +// break; +// } +// +// if (current_processor) +// return Status::Async; +// +// if (has_someone_to_wait) +// return Status::Wait; +// +// for (auto & element : processors) +// { +// if (element->prepare() == Status::NeedData) +// throw Exception("Pipeline stuck: " + element->getName() + " processor needs input data but no one is going to generate it", ErrorCodes::LOGICAL_ERROR); +// if (element->prepare() == Status::PortFull) +// throw Exception("Pipeline stuck: " + element->getName() + " processor has data in output port but no one is going to consume it", ErrorCodes::LOGICAL_ERROR); +// } +// +// return Status::Finished; +//} +// +// +//void ParallelPipelineExecutor::schedule(EventCounter & watch) +//{ +// if (!current_processor) +// throw Exception("Bad pipeline", ErrorCodes::LOGICAL_ERROR); +// +// if (current_status == Status::Async) +// { +// current_processor->schedule(watch); +// } +// else +// { +// { +// std::lock_guard lock(mutex); +// active_processors.insert(current_processor); +// } +// +// pool.schedule([processor = current_processor, &watch, this] +// { +// processor->work(); +// { +// std::lock_guard lock(mutex); +// active_processors.erase(processor); +// } +// watch.notify(); +// }); +// } +//} + +} + diff --git a/dbms/src/Processors/Executors/ParallelPipelineExecutor.h b/dbms/src/Processors/Executors/ParallelPipelineExecutor.h new file mode 100644 index 00000000000..4997f73f699 --- /dev/null +++ b/dbms/src/Processors/Executors/ParallelPipelineExecutor.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include +#include + +template +class ThreadPoolImpl; +class ThreadFromGlobalPool; +using ThreadPool = ThreadPoolImpl; + +namespace DB +{ + +/** Wraps pipeline in a single processor. + * This processor has no inputs and outputs and just executes the pipeline, + * performing all synchronous work within a threadpool. + */ +//class ParallelPipelineExecutor : public IProcessor +//{ +//private: +// Processors processors; +// ThreadPool & pool; +// +// std::set active_processors; +// std::mutex mutex; +// +// IProcessor * current_processor = nullptr; +// Status current_status; +// +//public: +// ParallelPipelineExecutor(const Processors & processors, ThreadPool & pool); +// +// String getName() const override { return "ParallelPipelineExecutor"; } +// +// Status prepare() override; +// void schedule(EventCounter & watch) override; +//}; + +} diff --git a/dbms/src/Processors/Executors/PipelineExecutor.cpp b/dbms/src/Processors/Executors/PipelineExecutor.cpp new file mode 100644 index 00000000000..9da53793e81 --- /dev/null +++ b/dbms/src/Processors/Executors/PipelineExecutor.cpp @@ -0,0 +1,653 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int TOO_MANY_ROWS_OR_BYTES; + extern const int QUOTA_EXPIRED; + extern const int QUERY_WAS_CANCELLED; +} + +static bool checkCanAddAdditionalInfoToException(const DB::Exception & exception) +{ + /// Don't add additional info to limits and quota exceptions, and in case of kill query (to pass tests). + return exception.code() != ErrorCodes::TOO_MANY_ROWS_OR_BYTES + && exception.code() != ErrorCodes::QUOTA_EXPIRED + && exception.code() != ErrorCodes::QUERY_WAS_CANCELLED; +} + +PipelineExecutor::PipelineExecutor(Processors & processors) + : processors(processors) + , cancelled(false) + , finished(false) + , num_processing_executors(0) + , expand_pipeline_task(nullptr) +{ + buildGraph(); +} + +bool PipelineExecutor::addEdges(UInt64 node) +{ + auto throwUnknownProcessor = [](const IProcessor * proc, const IProcessor * parent, bool from_input_port) + { + String msg = "Processor " + proc->getName() + " was found as " + (from_input_port ? "input" : "output") + + " for processor " + parent->getName() + ", but not found in list of processors."; + + throw Exception(msg, ErrorCodes::LOGICAL_ERROR); + }; + + const IProcessor * cur = graph[node].processor; + + auto add_edge = [&](auto & from_port, const IProcessor * to_proc, Edges & edges) + { + auto it = processors_map.find(to_proc); + if (it == processors_map.end()) + throwUnknownProcessor(to_proc, cur, true); + + UInt64 proc_num = it->second; + Edge * edge_ptr = nullptr; + + for (auto & edge : edges) + if (edge.to == proc_num) + edge_ptr = &edge; + + if (!edge_ptr) + { + edge_ptr = &edges.emplace_back(); + edge_ptr->to = proc_num; + } + + from_port.setVersion(&edge_ptr->version); + }; + + bool was_edge_added = false; + + auto & inputs = processors[node]->getInputs(); + auto from_input = graph[node].backEdges.size(); + + if (from_input < inputs.size()) + { + was_edge_added = true; + + for (auto it = std::next(inputs.begin(), from_input); it != inputs.end(); ++it) + { + const IProcessor * proc = &it->getOutputPort().getProcessor(); + add_edge(*it, proc, graph[node].backEdges); + } + } + + auto & outputs = processors[node]->getOutputs(); + auto from_output = graph[node].directEdges.size(); + + if (from_output < outputs.size()) + { + was_edge_added = true; + + for (auto it = std::next(outputs.begin(), from_output); it != outputs.end(); ++it) + { + const IProcessor * proc = &it->getInputPort().getProcessor(); + add_edge(*it, proc, graph[node].directEdges); + } + } + + return was_edge_added; +} + +void PipelineExecutor::buildGraph() +{ + UInt64 num_processors = processors.size(); + + graph.reserve(num_processors); + for (UInt64 node = 0; node < num_processors; ++node) + { + IProcessor * proc = processors[node].get(); + processors_map[proc] = node; + graph.emplace_back(proc, node); + } + + for (UInt64 node = 0; node < num_processors; ++node) + addEdges(node); +} + +void PipelineExecutor::addChildlessProcessorsToStack(Stack & stack) +{ + UInt64 num_processors = processors.size(); + for (UInt64 proc = 0; proc < num_processors; ++proc) + { + if (graph[proc].directEdges.empty()) + { + stack.push(proc); + graph[proc].status = ExecStatus::Preparing; + } + } +} + +static void executeJob(IProcessor * processor) +{ + try + { + processor->work(); + } + catch (Exception & exception) + { + if (checkCanAddAdditionalInfoToException(exception)) + exception.addMessage("While executing " + processor->getName() + " (" + + toString(reinterpret_cast(processor)) + ") "); + throw; + } +} + +void PipelineExecutor::addJob(ExecutionState * execution_state) +{ + auto job = [execution_state]() + { + try + { + Stopwatch watch; + executeJob(execution_state->processor); + execution_state->execution_time_ns += watch.elapsed(); + + ++execution_state->num_executed_jobs; + } + catch (...) + { + execution_state->exception = std::current_exception(); + } + }; + + execution_state->job = std::move(job); +} + +void PipelineExecutor::expandPipeline(Stack & stack, UInt64 pid) +{ + auto & cur_node = graph[pid]; + auto new_processors = cur_node.processor->expandPipeline(); + + for (const auto & processor : new_processors) + { + if (processors_map.count(processor.get())) + throw Exception("Processor " + processor->getName() + " was already added to pipeline.", + ErrorCodes::LOGICAL_ERROR); + + processors_map[processor.get()] = graph.size(); + graph.emplace_back(processor.get(), graph.size()); + } + + processors.insert(processors.end(), new_processors.begin(), new_processors.end()); + UInt64 num_processors = processors.size(); + + for (UInt64 node = 0; node < num_processors; ++node) + { + if (addEdges(node)) + { + if (graph[node].status == ExecStatus::Idle || graph[node].status == ExecStatus::New) + { + graph[node].status = ExecStatus::Preparing; + stack.push(node); + } + } + } +} + +bool PipelineExecutor::tryAddProcessorToStackIfUpdated(Edge & edge, Stack & stack) +{ + /// In this method we have ownership on edge, but node can be concurrently accessed. + + auto & node = graph[edge.to]; + + ExecStatus status = node.status.load(); + + /// Don't add processor if nothing was read from port. + if (status != ExecStatus::New && edge.version == edge.prev_version) + return false; + + if (status == ExecStatus::Finished) + return false; + + /// Signal that node need to be prepared. + node.need_to_be_prepared = true; + edge.prev_version = edge.version; + + /// Try to get ownership for node. + + /// Assume that current status is New or Idle. Otherwise, can't prepare node. + if (status != ExecStatus::New) + status = ExecStatus::Idle; + + /// Statuses but New and Idle are not interesting because they own node. + /// Prepare will be called in owning thread before changing status. + while (!node.status.compare_exchange_weak(status, ExecStatus::Preparing)) + if (!(status == ExecStatus::New || status == ExecStatus::Idle) || !node.need_to_be_prepared) + return false; + + stack.push(edge.to); + return true; + +} + +bool PipelineExecutor::prepareProcessor(UInt64 pid, Stack & children, Stack & parents, size_t thread_number, bool async) +{ + /// In this method we have ownership on node. + auto & node = graph[pid]; + + { + /// Stopwatch watch; + + /// Disable flag before prepare call. Otherwise, we can skip prepare request. + /// Prepare can be called more times than needed, but it's ok. + node.need_to_be_prepared = false; + + auto status = node.processor->prepare(); + + /// node.execution_state->preparation_time_ns += watch.elapsed(); + node.last_processor_status = status; + } + + auto add_neighbours_to_prepare_queue = [&] () + { + for (auto & edge : node.backEdges) + tryAddProcessorToStackIfUpdated(edge, parents); + + for (auto & edge : node.directEdges) + tryAddProcessorToStackIfUpdated(edge, children); + }; + + auto try_release_ownership = [&] () + { + /// This function can be called after expand pipeline, where node from outer scope is not longer valid. + auto & node_ = graph[pid]; + ExecStatus expected = ExecStatus::Idle; + node_.status = ExecStatus::Idle; + + if (node_.need_to_be_prepared) + { + while (!node_.status.compare_exchange_weak(expected, ExecStatus::Preparing)) + if (!(expected == ExecStatus::Idle) || !node_.need_to_be_prepared) + return; + + children.push(pid); + } + }; + + switch (node.last_processor_status) + { + case IProcessor::Status::NeedData: + { + add_neighbours_to_prepare_queue(); + try_release_ownership(); + + break; + } + case IProcessor::Status::PortFull: + { + add_neighbours_to_prepare_queue(); + try_release_ownership(); + + break; + } + case IProcessor::Status::Finished: + { + add_neighbours_to_prepare_queue(); + node.status = ExecStatus::Finished; + break; + } + case IProcessor::Status::Ready: + { + node.status = ExecStatus::Executing; + return true; + } + case IProcessor::Status::Async: + { + throw Exception("Async is temporary not supported.", ErrorCodes::LOGICAL_ERROR); + +// node.status = ExecStatus::Executing; +// addAsyncJob(pid); +// break; + } + case IProcessor::Status::Wait: + { + if (!async) + throw Exception("Processor returned status Wait before Async.", ErrorCodes::LOGICAL_ERROR); + break; + } + case IProcessor::Status::ExpandPipeline: + { + executor_contexts[thread_number]->task_list.emplace_back( + node.execution_state.get(), + &parents + ); + + ExpandPipelineTask * desired = &executor_contexts[thread_number]->task_list.back(); + ExpandPipelineTask * expected = nullptr; + + while (!expand_pipeline_task.compare_exchange_strong(expected, desired)) + { + doExpandPipeline(expected, true); + expected = nullptr; + } + + doExpandPipeline(desired, true); + + /// node is not longer valid after pipeline was expanded + graph[pid].need_to_be_prepared = true; + try_release_ownership(); + break; + } + } + + return false; +} + +void PipelineExecutor::doExpandPipeline(ExpandPipelineTask * task, bool processing) +{ + std::unique_lock lock(task->mutex); + + if (processing) + ++task->num_waiting_processing_threads; + + task->condvar.wait(lock, [&]() + { + return task->num_waiting_processing_threads >= num_processing_executors || expand_pipeline_task != task; + }); + + /// After condvar.wait() task may point to trash. Can change it only if it is still in expand_pipeline_task. + if (expand_pipeline_task == task) + { + expandPipeline(*task->stack, task->node_to_expand->processors_id); + + expand_pipeline_task = nullptr; + + lock.unlock(); + task->condvar.notify_all(); + } +} + +void PipelineExecutor::finish() +{ + { + std::lock_guard lock(task_queue_mutex); + finished = true; + } + + task_queue_condvar.notify_all(); +} + +void PipelineExecutor::execute(size_t num_threads) +{ + try + { + executeImpl(num_threads); + + /// Execution can be stopped because of exception. Check and rethrow if any. + for (auto & node : graph) + if (node.execution_state->exception) + std::rethrow_exception(node.execution_state->exception); + } + catch (Exception & exception) + { + if (checkCanAddAdditionalInfoToException(exception)) + exception.addMessage("\nCurrent state:\n" + dumpPipeline()); + + throw; + } + + if (cancelled) + return; + + bool all_processors_finished = true; + for (auto & node : graph) + if (node.status != ExecStatus::Finished) + all_processors_finished = false; + + if (!all_processors_finished) + throw Exception("Pipeline stuck. Current state:\n" + dumpPipeline(), ErrorCodes::LOGICAL_ERROR); +} + +void PipelineExecutor::executeSingleThread(size_t thread_num, size_t num_threads) +{ + UInt64 total_time_ns = 0; + UInt64 execution_time_ns = 0; + UInt64 processing_time_ns = 0; + UInt64 wait_time_ns = 0; + + Stopwatch total_time_watch; + ExecutionState * state = nullptr; + + auto prepare_processor = [&](UInt64 pid, Stack & children, Stack & parents) + { + try + { + return prepareProcessor(pid, children, parents, thread_num, false); + } + catch (...) + { + graph[pid].execution_state->exception = std::current_exception(); + finish(); + } + + return false; + }; + + using Queue = std::queue; + + auto prepare_all_processors = [&](Queue & queue, Stack & stack, Stack & children, Stack & parents) + { + while (!stack.empty() && !finished) + { + auto current_processor = stack.top(); + stack.pop(); + + if (prepare_processor(current_processor, children, parents)) + queue.push(graph[current_processor].execution_state.get()); + } + }; + + while (!finished) + { + + /// First, find any processor to execute. + /// Just travers graph and prepare any processor. + while (!finished) + { + std::unique_lock lock(task_queue_mutex); + + if (!task_queue.empty()) + { + state = task_queue.front(); + task_queue.pop(); + break; + } + + ++num_waiting_threads; + + if (num_waiting_threads == num_threads) + { + finished = true; + lock.unlock(); + task_queue_condvar.notify_all(); + break; + } + + task_queue_condvar.wait(lock, [&]() + { + return finished || !task_queue.empty(); + }); + + --num_waiting_threads; + } + + if (finished) + break; + + while (state) + { + if (finished) + break; + + addJob(state); + + { + Stopwatch execution_time_watch; + state->job(); + execution_time_ns += execution_time_watch.elapsed(); + } + + if (state->exception) + finish(); + + if (finished) + break; + + Stopwatch processing_time_watch; + + /// Try to execute neighbour processor. + { + Stack children; + Stack parents; + Queue queue; + + ++num_processing_executors; + while (auto task = expand_pipeline_task.load()) + doExpandPipeline(task, true); + + /// Execute again if can. + if (!prepare_processor(state->processors_id, children, parents)) + state = nullptr; + + /// Process all neighbours. Children will be on the top of stack, then parents. + prepare_all_processors(queue, children, children, parents); + + if (!state && !queue.empty()) + { + state = queue.front(); + queue.pop(); + } + + prepare_all_processors(queue, parents, parents, parents); + + if (!queue.empty()) + { + std::lock_guard lock(task_queue_mutex); + + while (!queue.empty() && !finished) + { + task_queue.push(queue.front()); + queue.pop(); + } + + task_queue_condvar.notify_all(); + } + + --num_processing_executors; + while (auto task = expand_pipeline_task.load()) + doExpandPipeline(task, false); + } + + processing_time_ns += processing_time_watch.elapsed(); + } + } + + total_time_ns = total_time_watch.elapsed(); + wait_time_ns = total_time_ns - execution_time_ns - processing_time_ns; + + LOG_TRACE(log, "Thread finished." + << " Total time: " << (total_time_ns / 1e9) << " sec." + << " Execution time: " << (execution_time_ns / 1e9) << " sec." + << " Processing time: " << (processing_time_ns / 1e9) << " sec." + << " Wait time: " << (wait_time_ns / 1e9) << "sec."); +} + +void PipelineExecutor::executeImpl(size_t num_threads) +{ + Stack stack; + + executor_contexts.reserve(num_threads); + for (size_t i = 0; i < num_threads; ++i) + executor_contexts.emplace_back(std::make_unique()); + + addChildlessProcessorsToStack(stack); + + while (!stack.empty()) + { + UInt64 proc = stack.top(); + stack.pop(); + + if (prepareProcessor(proc, stack, stack, 0, false)) + { + auto cur_state = graph[proc].execution_state.get(); + task_queue.push(cur_state); + } + } + + ThreadPool pool(num_threads); + + SCOPE_EXIT( + finish(); + pool.wait() + ); + + auto thread_group = CurrentThread::getGroup(); + + for (size_t i = 0; i < num_threads; ++i) + { + pool.schedule([this, thread_group, thread_num = i, num_threads] + { + /// ThreadStatus thread_status; + + if (thread_group) + CurrentThread::attachTo(thread_group); + + SCOPE_EXIT( + if (thread_group) + CurrentThread::detachQueryIfNotDetached(); + ); + + executeSingleThread(thread_num, num_threads); + }); + } + + pool.wait(); +} + +String PipelineExecutor::dumpPipeline() const +{ + for (auto & node : graph) + { + if (node.execution_state) + node.processor->setDescription( + "(" + std::to_string(node.execution_state->num_executed_jobs) + " jobs, execution time: " + + std::to_string(node.execution_state->execution_time_ns / 1e9) + " sec., preparation time: " + + std::to_string(node.execution_state->preparation_time_ns / 1e9) + " sec.)"); + } + + std::vector statuses; + std::vector proc_list; + statuses.reserve(graph.size()); + proc_list.reserve(graph.size()); + + for (auto & proc : graph) + { + proc_list.emplace_back(proc.processor); + statuses.emplace_back(proc.last_processor_status); + } + + WriteBufferFromOwnString out; + printPipeline(processors, statuses, out); + out.finish(); + + return out.str(); +} + +} diff --git a/dbms/src/Processors/Executors/PipelineExecutor.h b/dbms/src/Processors/Executors/PipelineExecutor.h new file mode 100644 index 00000000000..0994532f953 --- /dev/null +++ b/dbms/src/Processors/Executors/PipelineExecutor.h @@ -0,0 +1,195 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace DB +{ + + +/// Executes query pipeline. +class PipelineExecutor +{ +public: + /// Get pipeline as a set of processors. + /// Processors should represent full graph. All ports must be connected, all connected nodes are mentioned in set. + /// Executor doesn't own processors, just stores reference. + /// During pipeline execution new processors can appear. They will be added to existing set. + /// + /// Explicit graph representation is built in constructor. Throws if graph is not correct. + explicit PipelineExecutor(Processors & processors); + + /// Execute pipeline in multiple threads. Must be called once. + /// In case of exception during execution throws any occurred. + void execute(size_t num_threads); + + String getName() const { return "PipelineExecutor"; } + + const Processors & getProcessors() const { return processors; } + + /// Cancel execution. May be called from another thread. + void cancel() + { + cancelled = true; + finish(); + } + +private: + Processors & processors; + + struct Edge + { + UInt64 to = std::numeric_limits::max(); + + /// Edge version is increased when port's state is changed (e.g. when data is pushed). See Port.h for details. + /// To compare version with prev_version we can decide if neighbour processor need to be prepared. + UInt64 version = 0; + UInt64 prev_version = 0; + }; + + /// Use std::list because new ports can be added to processor during execution. + using Edges = std::list; + + /// Status for processor. + /// Can be owning or not. Owning means that executor who set this status can change node's data and nobody else can. + enum class ExecStatus + { + New, /// prepare wasn't called yet. Initial state. Non-owning. + Idle, /// prepare returned NeedData or PortFull. Non-owning. + Preparing, /// some executor is preparing processor, or processor is in task_queue. Owning. + Executing, /// prepare returned Ready and task is executing. Owning. + Finished, /// prepare returned Finished. Non-owning. + Async /// prepare returned Async. Owning. + }; + + /// Small structure with context of executing job. + struct ExecutionState + { + std::exception_ptr exception; + std::function job; + + IProcessor * processor; + UInt64 processors_id; + + /// Counters for profiling. + size_t num_executed_jobs = 0; + UInt64 execution_time_ns = 0; + UInt64 preparation_time_ns = 0; + }; + + struct Node + { + IProcessor * processor = nullptr; + Edges directEdges; + Edges backEdges; + + std::atomic status; + /// This flag can be set by any executor. + /// When enabled, any executor can try to atomically set Preparing state to status. + std::atomic_bool need_to_be_prepared; + /// Last state for profiling. + IProcessor::Status last_processor_status = IProcessor::Status::NeedData; + + std::unique_ptr execution_state; + + Node(IProcessor * processor_, UInt64 processor_id) + : processor(processor_), status(ExecStatus::New), need_to_be_prepared(false) + { + execution_state = std::make_unique(); + execution_state->processor = processor; + execution_state->processors_id = processor_id; + } + + Node(Node && other) noexcept + : processor(other.processor), status(other.status.load()) + , need_to_be_prepared(other.need_to_be_prepared.load()), execution_state(std::move(other.execution_state)) + { + } + }; + + using Nodes = std::vector; + + Nodes graph; + + using Stack = std::stack; + + using TaskQueue = std::queue; + + /// Queue with pointers to tasks. Each thread will concurrently read from it until finished flag is set. + /// Stores processors need to be prepared. Preparing status is already set for them. + TaskQueue task_queue; + std::mutex task_queue_mutex; + std::condition_variable task_queue_condvar; + + std::atomic_bool cancelled; + std::atomic_bool finished; + + Poco::Logger * log = &Poco::Logger::get("PipelineExecutor"); + + /// Num threads waiting condvar. Last thread finish execution if task_queue is empty. + size_t num_waiting_threads = 0; + + /// Things to stop execution to expand pipeline. + struct ExpandPipelineTask + { + ExecutionState * node_to_expand; + Stack * stack; + size_t num_waiting_processing_threads = 0; + std::mutex mutex; + std::condition_variable condvar; + + ExpandPipelineTask(ExecutionState * node_to_expand_, Stack * stack_) + : node_to_expand(node_to_expand_), stack(stack_) {} + }; + + std::atomic num_processing_executors; + std::atomic expand_pipeline_task; + + /// Context for each thread. + struct ExecutorContext + { + /// Will store context for all expand pipeline tasks (it's easy and we don't expect many). + /// This can be solved by using atomic shard ptr. + std::list task_list; + }; + + std::vector> executor_contexts; + + /// Processor ptr -> node number + using ProcessorsMap = std::unordered_map; + ProcessorsMap processors_map; + + /// Graph related methods. + bool addEdges(UInt64 node); + void buildGraph(); + void expandPipeline(Stack & stack, UInt64 pid); + + /// Pipeline execution related methods. + void addChildlessProcessorsToStack(Stack & stack); + bool tryAddProcessorToStackIfUpdated(Edge & edge, Stack & stack); + static void addJob(ExecutionState * execution_state); + // TODO: void addAsyncJob(UInt64 pid); + + /// Prepare processor with pid number. + /// Check parents and children of current processor and push them to stacks if they also need to be prepared. + /// If processor wants to be expanded, ExpandPipelineTask from thread_number's execution context will be used. + bool prepareProcessor(size_t pid, Stack & children, Stack & parents, size_t thread_number, bool async); + void doExpandPipeline(ExpandPipelineTask * task, bool processing); + + void executeImpl(size_t num_threads); + void executeSingleThread(size_t thread_num, size_t num_threads); + void finish(); + + String dumpPipeline() const; +}; + +using PipelineExecutorPtr = std::shared_ptr; + +} diff --git a/dbms/src/Processors/Executors/SequentialPipelineExecutor.cpp b/dbms/src/Processors/Executors/SequentialPipelineExecutor.cpp new file mode 100644 index 00000000000..d660936eff8 --- /dev/null +++ b/dbms/src/Processors/Executors/SequentialPipelineExecutor.cpp @@ -0,0 +1,79 @@ +#include +#include + + +namespace DB +{ + +//SequentialPipelineExecutor::SequentialPipelineExecutor(const Processors & processors) +// : processors(processors) +//{ +//} +// +// +//SequentialPipelineExecutor::Status SequentialPipelineExecutor::prepare() +//{ +// current_processor = nullptr; +// +// bool has_someone_to_wait = false; +// Status found_status = Status::Finished; +// +// for (auto & element : processors) +// { +// traverse(*element, +// [&] (IProcessor & processor) +// { +// Status status = processor.prepare(); +// +// if (status == Status::Wait) +// has_someone_to_wait = true; +// +// if (status == Status::Ready || status == Status::Async) +// { +// current_processor = &processor; +// found_status = status; +// } +// +// return status; +// }); +// +// if (current_processor) +// break; +// } +// +// if (current_processor) +// return found_status; +// if (has_someone_to_wait) +// return Status::Wait; +// +// for (auto & element : processors) +// { +// if (element->prepare() == Status::NeedData) +// throw Exception("Pipeline stuck: " + element->getName() + " processor needs input data but no one is going to generate it", ErrorCodes::LOGICAL_ERROR); +// if (element->prepare() == Status::PortFull) +// throw Exception("Pipeline stuck: " + element->getName() + " processor has data in output port but no one is going to consume it", ErrorCodes::LOGICAL_ERROR); +// } +// +// return Status::Finished; +//} +// +// +//void SequentialPipelineExecutor::work() +//{ +// if (!current_processor) +// throw Exception("Bad pipeline", ErrorCodes::LOGICAL_ERROR); +// +// current_processor->work(); +//} +// +// +//void SequentialPipelineExecutor::schedule(EventCounter & watch) +//{ +// if (!current_processor) +// throw Exception("Bad pipeline", ErrorCodes::LOGICAL_ERROR); +// +// current_processor->schedule(watch); +//} + +} + diff --git a/dbms/src/Processors/Executors/SequentialPipelineExecutor.h b/dbms/src/Processors/Executors/SequentialPipelineExecutor.h new file mode 100644 index 00000000000..5dbd8b73fee --- /dev/null +++ b/dbms/src/Processors/Executors/SequentialPipelineExecutor.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include + + +namespace DB +{ + +/** Wraps pipeline in a single processor. + * This processor has no inputs and outputs and just executes the pipeline, + * performing all synchronous work from the current thread. + */ +//class SequentialPipelineExecutor : public IProcessor +//{ +//private: +// Processors processors; +// IProcessor * current_processor = nullptr; +// +//public: +// SequentialPipelineExecutor(const Processors & processors); +// +// String getName() const override { return "SequentialPipelineExecutor"; } +// +// Status prepare() override; +// void work() override; +// void schedule(EventCounter & watch) override; +//}; + +} diff --git a/dbms/src/Processors/Executors/traverse.h b/dbms/src/Processors/Executors/traverse.h new file mode 100644 index 00000000000..2fd89adcb43 --- /dev/null +++ b/dbms/src/Processors/Executors/traverse.h @@ -0,0 +1,30 @@ +#pragma once + +#include + + +namespace DB +{ + +/// Look for first Ready or Async processor by depth-first search in needed input ports and full output ports. +/// NOTE: Pipeline must not have cycles. +//template +//void traverse(IProcessor & processor, Visit && visit) +//{ +// IProcessor::Status status = visit(processor); +// +// if (status == IProcessor::Status::Ready || status == IProcessor::Status::Async) +// return; +// +// if (status == IProcessor::Status::NeedData) +// for (auto & input : processor.getInputs()) +// if (input.isNeeded() && !input.hasData()) +// traverse(input.getOutputPort().getProcessor(), std::forward(visit)); +// +// if (status == IProcessor::Status::PortFull) +// for (auto & output : processor.getOutputs()) +// if (output.hasData()) +// traverse(output.getInputPort().getProcessor(), std::forward(visit)); +//} + +} diff --git a/dbms/src/Processors/ForkProcessor.cpp b/dbms/src/Processors/ForkProcessor.cpp new file mode 100644 index 00000000000..30903f22433 --- /dev/null +++ b/dbms/src/Processors/ForkProcessor.cpp @@ -0,0 +1,81 @@ +#include + + +namespace DB +{ + +ForkProcessor::Status ForkProcessor::prepare() +{ + auto & input = inputs.front(); + + /// Check can output. + + bool all_finished = true; + bool all_can_push = true; + size_t num_active_outputs = 0; + + for (const auto & output : outputs) + { + if (!output.isFinished()) + { + all_finished = false; + ++num_active_outputs; + + /// The order is important. + if (!output.canPush()) + all_can_push = false; + } + } + + if (all_finished) + { + input.close(); + return Status::Finished; + } + + if (!all_can_push) + { + input.setNotNeeded(); + return Status::PortFull; + } + + /// Check can input. + + if (input.isFinished()) + { + for (auto & output : outputs) + output.finish(); + + return Status::Finished; + } + + input.setNeeded(); + + if (!input.hasData()) + return Status::NeedData; + + /// Move data. + + auto data = input.pull(); + size_t num_processed_outputs = 0; + + for (auto & output : outputs) + { + if (!output.isFinished()) /// Skip finished outputs. + { + ++num_processed_outputs; + if (num_processed_outputs == num_active_outputs) + output.push(std::move(data)); /// Can push because no full or unneeded outputs. + else + output.push(data.clone()); + } + } + + /// Now, we pulled from input. It must be empty. + return Status::NeedData; +} + +} + + + diff --git a/dbms/src/Processors/ForkProcessor.h b/dbms/src/Processors/ForkProcessor.h new file mode 100644 index 00000000000..8839f73584f --- /dev/null +++ b/dbms/src/Processors/ForkProcessor.h @@ -0,0 +1,35 @@ +#pragma once + +#include + + +namespace DB +{ + +/** Has one input and arbitrary non zero number of outputs. + * All of them have the same structure. + * + * Pulls data input and copies it to every output. + * You may have heard about it under the name 'tee'. + * + * Doesn't do any heavy calculations. + * Preserves an order of data. + */ +class ForkProcessor : public IProcessor +{ +public: + ForkProcessor(const Block & header, size_t num_outputs) + : IProcessor(InputPorts{header}, OutputPorts(num_outputs, header)) + { + } + + String getName() const override { return "Fork"; } + + Status prepare() override; + + InputPort & getInputPort() { return inputs.front(); } +}; + +} + + diff --git a/dbms/src/Processors/Formats/IInputFormat.h b/dbms/src/Processors/Formats/IInputFormat.h new file mode 100644 index 00000000000..7e4e00c1a33 --- /dev/null +++ b/dbms/src/Processors/Formats/IInputFormat.h @@ -0,0 +1,32 @@ +#pragma once + +#include + + +namespace DB +{ + +class ReadBuffer; + +/** Input format is a source, that reads data from ReadBuffer. + */ +class IInputFormat : public ISource +{ +protected: + + /// Skip GCC warning: ‘maybe_unused’ attribute ignored +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wattributes" + + ReadBuffer & in [[maybe_unused]]; + +#pragma GCC diagnostic pop + +public: + IInputFormat(Block header, ReadBuffer & in) + : ISource(std::move(header)), in(in) + { + } +}; + +} diff --git a/dbms/src/Processors/Formats/IOutputFormat.cpp b/dbms/src/Processors/Formats/IOutputFormat.cpp new file mode 100644 index 00000000000..63e846aa796 --- /dev/null +++ b/dbms/src/Processors/Formats/IOutputFormat.cpp @@ -0,0 +1,78 @@ +#include +#include + + +namespace DB +{ + +IOutputFormat::IOutputFormat(const Block & header, WriteBuffer & out) + : IProcessor({header, header, header}, {}), out(out) +{ +} + +IOutputFormat::Status IOutputFormat::prepare() +{ + if (has_input) + return Status::Ready; + + for (auto kind : {Main, Totals, Extremes}) + { + auto & input = getPort(kind); + + if (kind != Main && !input.isConnected()) + continue; + + if (input.isFinished()) + continue; + + input.setNeeded(); + + if (!input.hasData()) + return Status::NeedData; + + current_chunk = input.pull(); + current_block_kind = kind; + has_input = true; + return Status::Ready; + } + + finished = true; + + if (!finalized) + return Status::Ready; + + return Status::Finished; +} + +void IOutputFormat::work() +{ + if (finished && !finalized) + { + finalize(); + finalized = true; + return; + } + + switch (current_block_kind) + { + case Main: + consume(std::move(current_chunk)); + break; + case Totals: + consumeTotals(std::move(current_chunk)); + break; + case Extremes: + consumeExtremes(std::move(current_chunk)); + break; + } + + has_input = false; +} + +void IOutputFormat::flush() +{ + out.next(); +} + +} + diff --git a/dbms/src/Processors/Formats/IOutputFormat.h b/dbms/src/Processors/Formats/IOutputFormat.h new file mode 100644 index 00000000000..280f64593b7 --- /dev/null +++ b/dbms/src/Processors/Formats/IOutputFormat.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include + + +namespace DB +{ + +class WriteBuffer; + +/** Output format have three inputs and no outputs. It writes data from WriteBuffer. + * + * First input is for main resultset, second is for "totals" and third is for "extremes". + * It's not necessarily to connect "totals" or "extremes" ports (they may remain dangling). + * + * Data from input ports are pulled in order: first, from main input, then totals, then extremes. + * + * By default, data for "totals" and "extremes" is ignored. + */ +class IOutputFormat : public IProcessor +{ +public: + enum PortKind { Main = 0, Totals = 1, Extremes = 2 }; + +protected: + WriteBuffer & out; + + Chunk current_chunk; + PortKind current_block_kind = PortKind::Main; + bool has_input = false; + bool finished = false; + bool finalized = false; + + virtual void consume(Chunk) = 0; + virtual void consumeTotals(Chunk) {} + virtual void consumeExtremes(Chunk) {} + virtual void finalize() {} + +public: + IOutputFormat(const Block & header, WriteBuffer & out); + + Status prepare() override; + void work() override; + + /// Flush output buffers if any. + virtual void flush(); + + /// Value for rows_before_limit_at_least field. + virtual void setRowsBeforeLimit(size_t /*rows_before_limit*/) {} + + /// Notify about progress. Method could be called from different threads. + /// Passed value are delta, that must be summarized. + virtual void onProgress(const Progress & /*progress*/) {} + + /// Content-Type to set when sending HTTP response. + virtual std::string getContentType() const { return "text/plain; charset=UTF-8"; } + + InputPort & getPort(PortKind kind) { return *std::next(inputs.begin(), kind); } +}; +} + diff --git a/dbms/src/Processors/Formats/IRowInputFormat.cpp b/dbms/src/Processors/Formats/IRowInputFormat.cpp new file mode 100644 index 00000000000..b0212d2b89f --- /dev/null +++ b/dbms/src/Processors/Formats/IRowInputFormat.cpp @@ -0,0 +1,151 @@ +#include +#include // toString + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int CANNOT_PARSE_INPUT_ASSERTION_FAILED; + extern const int CANNOT_PARSE_QUOTED_STRING; + extern const int CANNOT_PARSE_DATE; + extern const int CANNOT_PARSE_DATETIME; + extern const int CANNOT_READ_ARRAY_FROM_TEXT; + extern const int CANNOT_PARSE_NUMBER; + extern const int CANNOT_PARSE_UUID; + extern const int TOO_LARGE_STRING_SIZE; + extern const int INCORRECT_NUMBER_OF_COLUMNS; +} + + +static bool isParseError(int code) +{ + return code == ErrorCodes::CANNOT_PARSE_INPUT_ASSERTION_FAILED + || code == ErrorCodes::CANNOT_PARSE_QUOTED_STRING + || code == ErrorCodes::CANNOT_PARSE_DATE + || code == ErrorCodes::CANNOT_PARSE_DATETIME + || code == ErrorCodes::CANNOT_READ_ARRAY_FROM_TEXT + || code == ErrorCodes::CANNOT_PARSE_NUMBER + || code == ErrorCodes::CANNOT_PARSE_UUID + || code == ErrorCodes::TOO_LARGE_STRING_SIZE; +} + + +Chunk IRowInputFormat::generate() +{ + if (total_rows == 0) + readPrefix(); + + const Block & header = getPort().getHeader(); + + size_t num_columns = header.columns(); + MutableColumns columns = header.cloneEmptyColumns(); + size_t prev_rows = total_rows; + + auto chunk_missing_values = std::make_unique(); + + try + { + for (size_t rows = 0; rows < params.max_block_size; ++rows) + { + try + { + ++total_rows; + + RowReadExtension info; + if (!readRow(columns, info)) + break; + + for (size_t column_idx = 0; column_idx < info.read_columns.size(); ++column_idx) + { + if (!info.read_columns[column_idx]) + { + size_t column_size = columns[column_idx]->size(); + if (column_size == 0) + throw Exception("Unexpected empty column", ErrorCodes::INCORRECT_NUMBER_OF_COLUMNS); + chunk_missing_values->setBit(column_idx, column_size - 1); + } + } + } + catch (Exception & e) + { + /// Logic for possible skipping of errors. + + if (!isParseError(e.code())) + throw; + + if (params.allow_errors_num == 0 && params.allow_errors_ratio == 0) + throw; + + ++num_errors; + Float64 current_error_ratio = static_cast(num_errors) / total_rows; + + if (num_errors > params.allow_errors_num + && current_error_ratio > params.allow_errors_ratio) + { + e.addMessage("(Already have " + toString(num_errors) + " errors" + " out of " + toString(total_rows) + " rows" + ", which is " + toString(current_error_ratio) + " of all rows)"); + throw; + } + + if (!allowSyncAfterError()) + { + e.addMessage("(Input format doesn't allow to skip errors)"); + throw; + } + + syncAfterError(); + + /// Truncate all columns in block to minimal size (remove values, that was appended to only part of columns). + + size_t min_size = std::numeric_limits::max(); + for (size_t column_idx = 0; column_idx < num_columns; ++column_idx) + min_size = std::min(min_size, columns[column_idx]->size()); + + for (size_t column_idx = 0; column_idx < num_columns; ++column_idx) + { + auto & column = columns[column_idx]; + if (column->size() > min_size) + column->popBack(column->size() - min_size); + } + } + } + } + catch (Exception & e) + { + if (!isParseError(e.code())) + throw; + + String verbose_diagnostic; + try + { + verbose_diagnostic = getDiagnosticInfo(); + } + catch (...) + { + /// Error while trying to obtain verbose diagnostic. Ok to ignore. + } + + e.addMessage("(at row " + toString(total_rows) + ")\n" + verbose_diagnostic); + throw; + } + + if (columns.empty() || columns[0]->empty()) + { + readSuffix(); + return {}; + } + + Chunk chunk(std::move(columns), total_rows - prev_rows); + chunk.setChunkInfo(std::move(chunk_missing_values)); + return chunk; +} + +void IRowInputFormat::syncAfterError() +{ + throw Exception("Method syncAfterError is not implemented for input format", ErrorCodes::NOT_IMPLEMENTED); +} + +} diff --git a/dbms/src/Processors/Formats/IRowInputFormat.h b/dbms/src/Processors/Formats/IRowInputFormat.h new file mode 100644 index 00000000000..9d0ee7cb0c9 --- /dev/null +++ b/dbms/src/Processors/Formats/IRowInputFormat.h @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include + + +namespace DB +{ + +/// Contains extra information about read data. +struct RowReadExtension +{ + /// IRowInputStream.read() output. It contains non zero for columns that actually read from the source and zero otherwise. + /// It's used to attach defaults for partially filled rows. + std::vector read_columns; +}; + +/// Common parameters for generating blocks. +struct RowInputFormatParams +{ + size_t max_block_size; + + UInt64 allow_errors_num; + Float64 allow_errors_ratio; +}; + +///Row oriented input format: reads data row by row. +class IRowInputFormat : public IInputFormat +{ +public: + using Params = RowInputFormatParams; + + IRowInputFormat( + Block header, + ReadBuffer & in_, + Params params) + : IInputFormat(std::move(header), in_), params(params) + { + } + + Chunk generate() override; + +protected: + /** Read next row and append it to the columns. + * If no more rows - return false. + */ + virtual bool readRow(MutableColumns & columns, RowReadExtension & extra) = 0; + + virtual void readPrefix() {} /// delimiter before begin of result + virtual void readSuffix() {} /// delimiter after end of result + + /// Skip data until next row. + /// This is intended for text streams, that allow skipping of errors. + /// By default - throws not implemented exception. + virtual bool allowSyncAfterError() const { return false; } + virtual void syncAfterError(); + + /// In case of parse error, try to roll back and parse last one or two rows very carefully + /// and collect as much as possible diagnostic information about error. + /// If not implemented, returns empty string. + virtual std::string getDiagnosticInfo() { return {}; } + +private: + Params params; + + size_t total_rows = 0; + size_t num_errors = 0; +}; + +} + diff --git a/dbms/src/Processors/Formats/IRowOutputFormat.cpp b/dbms/src/Processors/Formats/IRowOutputFormat.cpp new file mode 100644 index 00000000000..6db2802f232 --- /dev/null +++ b/dbms/src/Processors/Formats/IRowOutputFormat.cpp @@ -0,0 +1,101 @@ +#include +#include +#include + + +namespace DB +{ + +void IRowOutputFormat::consume(DB::Chunk chunk) +{ + writePrefixIfNot(); + + auto num_rows = chunk.getNumRows(); + auto & columns = chunk.getColumns(); + + for (UInt64 row = 0; row < num_rows; ++row) + { + if (!first_row) + writeRowBetweenDelimiter(); + first_row = false; + + write(columns, row); + } +} + +void IRowOutputFormat::consumeTotals(DB::Chunk chunk) +{ + writePrefixIfNot(); + writeSuffixIfNot(); + + auto num_rows = chunk.getNumRows(); + if (num_rows != 1) + throw Exception("Got " + toString(num_rows) + " in totals chunk, expected 1", ErrorCodes::LOGICAL_ERROR); + + auto & columns = chunk.getColumns(); + + writeBeforeTotals(); + writeTotals(columns, 0); + writeAfterTotals(); +} + +void IRowOutputFormat::consumeExtremes(DB::Chunk chunk) +{ + writePrefixIfNot(); + writeSuffixIfNot(); + + auto num_rows = chunk.getNumRows(); + auto & columns = chunk.getColumns(); + if (num_rows != 2) + throw Exception("Got " + toString(num_rows) + " in extremes chunk, expected 2", ErrorCodes::LOGICAL_ERROR); + + writeBeforeExtremes(); + writeMinExtreme(columns, 0); + writeRowBetweenDelimiter(); + writeMaxExtreme(columns, 1); + writeAfterExtremes(); +} + +void IRowOutputFormat::finalize() +{ + writePrefixIfNot(); + writeSuffixIfNot(); + writeLastSuffix(); +} + +void IRowOutputFormat::write(const Columns & columns, size_t row_num) +{ + size_t num_columns = columns.size(); + + writeRowStartDelimiter(); + + for (size_t i = 0; i < num_columns; ++i) + { + if (i != 0) + writeFieldDelimiter(); + + writeField(*columns[i], *types[i], row_num); + } + + writeRowEndDelimiter(); +} + +void IRowOutputFormat::writeMinExtreme(const DB::Columns & columns, size_t row_num) +{ + write(columns, row_num); +} + +void IRowOutputFormat::writeMaxExtreme(const DB::Columns & columns, size_t row_num) +{ + write(columns, row_num); +} + +void IRowOutputFormat::writeTotals(const DB::Columns & columns, size_t row_num) +{ + write(columns, row_num); +} + +} + + + diff --git a/dbms/src/Processors/Formats/IRowOutputFormat.h b/dbms/src/Processors/Formats/IRowOutputFormat.h new file mode 100644 index 00000000000..09bfe17a1b5 --- /dev/null +++ b/dbms/src/Processors/Formats/IRowOutputFormat.h @@ -0,0 +1,80 @@ +#pragma once + +#include +#include + + +namespace DB +{ + +class WriteBuffer; + +/** Output format that writes data row by row. + */ +class IRowOutputFormat : public IOutputFormat +{ +protected: + DataTypes types; + + void consume(Chunk chunk) override; + void consumeTotals(Chunk chunk) override; + void consumeExtremes(Chunk chunk) override; + void finalize() override; + +public: + IRowOutputFormat(const Block & header, WriteBuffer & out_) + : IOutputFormat(header, out_), types(header.getDataTypes()) + { + } + + /** Write a row. + * Default implementation calls methods to write single values and delimiters + * (except delimiter between rows (writeRowBetweenDelimiter())). + */ + virtual void write(const Columns & columns, size_t row_num); + virtual void writeMinExtreme(const Columns & columns, size_t row_num); + virtual void writeMaxExtreme(const Columns & columns, size_t row_num); + virtual void writeTotals(const Columns & columns, size_t row_num); + + /** Write single value. */ + virtual void writeField(const IColumn & column, const IDataType & type, size_t row_num) = 0; + + /** Write delimiter. */ + virtual void writeFieldDelimiter() {} /// delimiter between values + virtual void writeRowStartDelimiter() {} /// delimiter before each row + virtual void writeRowEndDelimiter() {} /// delimiter after each row + virtual void writeRowBetweenDelimiter() {} /// delimiter between rows + virtual void writePrefix() {} /// delimiter before resultset + virtual void writeSuffix() {} /// delimiter after resultset + virtual void writeBeforeTotals() {} + virtual void writeAfterTotals() {} + virtual void writeBeforeExtremes() {} + virtual void writeAfterExtremes() {} + virtual void writeLastSuffix() {} /// Write something after resultset, totals end extremes. + +private: + bool first_row = true; + bool prefix_written = false; + bool suffix_written = false; + + void writePrefixIfNot() + { + if (!prefix_written) + writePrefix(); + + prefix_written = true; + } + + void writeSuffixIfNot() + { + if (!suffix_written) + writeSuffix(); + + suffix_written = true; + } + +}; + +} + + diff --git a/dbms/src/Processors/Formats/Impl/BinaryRowInputFormat.cpp b/dbms/src/Processors/Formats/Impl/BinaryRowInputFormat.cpp new file mode 100644 index 00000000000..20f40fe1e41 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/BinaryRowInputFormat.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include + + +namespace DB +{ + +BinaryRowInputFormat::BinaryRowInputFormat(ReadBuffer & in_, Block header, Params params, bool with_names_, bool with_types_) + : IRowInputFormat(std::move(header), in_, params), with_names(with_names_), with_types(with_types_) +{ +} + + +bool BinaryRowInputFormat::readRow(MutableColumns & columns, RowReadExtension &) +{ + if (in.eof()) + return false; + + size_t num_columns = columns.size(); + for (size_t i = 0; i < num_columns; ++i) + getPort().getHeader().getByPosition(i).type->deserializeBinary(*columns[i], in); + + return true; +} + + +void BinaryRowInputFormat::readPrefix() +{ + /// NOTE The header is completely ignored. This can be easily improved. + + UInt64 columns = 0; + String tmp; + + if (with_names || with_types) + { + readVarUInt(columns, in); + } + + if (with_names) + { + for (size_t i = 0; i < columns; ++i) + { + readStringBinary(tmp, in); + } + } + + if (with_types) + { + for (size_t i = 0; i < columns; ++i) + { + readStringBinary(tmp, in); + } + } +} + + +void registerInputFormatProcessorRowBinary(FormatFactory & factory) +{ + factory.registerInputFormatProcessor("RowBinary", []( + ReadBuffer & buf, + const Block & sample, + const Context &, + const IRowInputFormat::Params & params, + const FormatSettings &) + { + return std::make_shared(buf, sample, params, false, false); + }); + + factory.registerInputFormatProcessor("RowBinaryWithNamesAndTypes", []( + ReadBuffer & buf, + const Block & sample, + const Context &, + const IRowInputFormat::Params & params, + const FormatSettings &) + { + return std::make_shared(buf, sample, params, true, true); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/BinaryRowInputFormat.h b/dbms/src/Processors/Formats/Impl/BinaryRowInputFormat.h new file mode 100644 index 00000000000..9a5a3fe63e1 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/BinaryRowInputFormat.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + + +namespace DB +{ + +class ReadBuffer; + + +/** A stream for inputting data in a binary line-by-line format. + */ +class BinaryRowInputFormat : public IRowInputFormat +{ +public: + BinaryRowInputFormat(ReadBuffer & in_, Block header, Params params, bool with_names_, bool with_types_); + + bool readRow(MutableColumns & columns, RowReadExtension &) override; + void readPrefix() override; + + String getName() const override { return "BinaryRowInputFormat"; } + +private: + bool with_names; + bool with_types; +}; + +} diff --git a/dbms/src/Processors/Formats/Impl/BinaryRowOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/BinaryRowOutputFormat.cpp new file mode 100644 index 00000000000..fb728d1293b --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/BinaryRowOutputFormat.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +BinaryRowOutputFormat::BinaryRowOutputFormat(WriteBuffer & out_, const Block & header, bool with_names_, bool with_types_) + : IRowOutputFormat(header, out_), with_names(with_names_), with_types(with_types_) +{ +} + +void BinaryRowOutputFormat::writePrefix() +{ + auto & header = getPort(PortKind::Main).getHeader(); + size_t columns = header.columns(); + + if (with_names || with_types) + { + writeVarUInt(columns, out); + } + + if (with_names) + { + for (size_t i = 0; i < columns; ++i) + { + writeStringBinary(header.safeGetByPosition(i).name, out); + } + } + + if (with_types) + { + for (size_t i = 0; i < columns; ++i) + { + writeStringBinary(header.safeGetByPosition(i).type->getName(), out); + } + } +} + +void BinaryRowOutputFormat::writeField(const IColumn & column, const IDataType & type, size_t row_num) +{ + type.serializeBinary(column, row_num, out); +} + + +void registerOutputFormatProcessorRowBinary(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("RowBinary", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings &) + { + return std::make_shared(buf, sample, false, false); + }); + + factory.registerOutputFormatProcessor("RowBinaryWithNamesAndTypes", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings &) + { + return std::make_shared(buf, sample, true, true); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/BinaryRowOutputFormat.h b/dbms/src/Processors/Formats/Impl/BinaryRowOutputFormat.h new file mode 100644 index 00000000000..23e7be0a558 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/BinaryRowOutputFormat.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + + +namespace DB +{ + +class IColumn; +class IDataType; +class WriteBuffer; + + +/** A stream for outputting data in a binary line-by-line format. + */ +class BinaryRowOutputFormat: public IRowOutputFormat +{ +public: + BinaryRowOutputFormat(WriteBuffer & out_, const Block & header, bool with_names_, bool with_types_); + + String getName() const override { return "BinaryRowOutputFormat"; } + + void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; + void writePrefix() override; + + String getContentType() const override { return "application/octet-stream"; } + +protected: + bool with_names; + bool with_types; +}; + +} + diff --git a/dbms/src/Processors/Formats/Impl/CMakeLists.txt b/dbms/src/Processors/Formats/Impl/CMakeLists.txt new file mode 100644 index 00000000000..65172356645 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/CMakeLists.txt @@ -0,0 +1,3 @@ +if (ENABLE_TESTS) + add_subdirectory (tests) +endif () diff --git a/dbms/src/Processors/Formats/Impl/CSVRowInputFormat.cpp b/dbms/src/Processors/Formats/Impl/CSVRowInputFormat.cpp new file mode 100644 index 00000000000..3038c9e02f6 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/CSVRowInputFormat.cpp @@ -0,0 +1,367 @@ +#include +#include + +#include +#include +#include + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int INCORRECT_DATA; + extern const int LOGICAL_ERROR; +} + + +CSVRowInputFormat::CSVRowInputFormat( + ReadBuffer & in_, Block header, Params params, bool with_names_, const FormatSettings & format_settings) + : IRowInputFormat(std::move(header), in_, params), with_names(with_names_), format_settings(format_settings) +{ + auto & sample = getPort().getHeader(); + size_t num_columns = sample.columns(); + data_types.resize(num_columns); + for (size_t i = 0; i < num_columns; ++i) + data_types[i] = sample.safeGetByPosition(i).type; +} + + +static void skipEndOfLine(ReadBuffer & istr) +{ + /// \n (Unix) or \r\n (DOS/Windows) or \n\r (Mac OS Classic) + + if (*istr.position() == '\n') + { + ++istr.position(); + if (!istr.eof() && *istr.position() == '\r') + ++istr.position(); + } + else if (*istr.position() == '\r') + { + ++istr.position(); + if (!istr.eof() && *istr.position() == '\n') + ++istr.position(); + else + throw Exception("Cannot parse CSV format: found \\r (CR) not followed by \\n (LF)." + " Line must end by \\n (LF) or \\r\\n (CR LF) or \\n\\r.", ErrorCodes::INCORRECT_DATA); + } + else if (!istr.eof()) + throw Exception("Expected end of line", ErrorCodes::INCORRECT_DATA); +} + + +static void skipDelimiter(ReadBuffer & istr, const char delimiter, bool is_last_column) +{ + if (is_last_column) + { + if (istr.eof()) + return; + + /// we support the extra delimiter at the end of the line + if (*istr.position() == delimiter) + { + ++istr.position(); + if (istr.eof()) + return; + } + + skipEndOfLine(istr); + } + else + assertChar(delimiter, istr); +} + + +/// Skip `whitespace` symbols allowed in CSV. +static inline void skipWhitespacesAndTabs(ReadBuffer & buf) +{ + while (!buf.eof() + && (*buf.position() == ' ' + || *buf.position() == '\t')) + ++buf.position(); +} + + +static void skipRow(ReadBuffer & istr, const FormatSettings::CSV & settings, size_t num_columns) +{ + String tmp; + for (size_t i = 0; i < num_columns; ++i) + { + skipWhitespacesAndTabs(istr); + readCSVString(tmp, istr, settings); + skipWhitespacesAndTabs(istr); + + skipDelimiter(istr, settings.delimiter, i + 1 == num_columns); + } +} + + +void CSVRowInputFormat::readPrefix() +{ + /// In this format, we assume, that if first string field contain BOM as value, it will be written in quotes, + /// so BOM at beginning of stream cannot be confused with BOM in first string value, and it is safe to skip it. + skipBOMIfExists(in); + + size_t num_columns = data_types.size(); + String tmp; + + if (with_names) + skipRow(in, format_settings.csv, num_columns); +} + + +bool CSVRowInputFormat::readRow(MutableColumns & columns, RowReadExtension &) +{ + if (in.eof()) + return false; + + updateDiagnosticInfo(); + + size_t size = data_types.size(); + + for (size_t i = 0; i < size; ++i) + { + skipWhitespacesAndTabs(in); + data_types[i]->deserializeAsTextCSV(*columns[i], in, format_settings); + skipWhitespacesAndTabs(in); + + skipDelimiter(in, format_settings.csv.delimiter, i + 1 == size); + } + + return true; +} + + +String CSVRowInputFormat::getDiagnosticInfo() +{ + if (in.eof()) /// Buffer has gone, cannot extract information about what has been parsed. + return {}; + + WriteBufferFromOwnString out; + + auto & header = getPort().getHeader(); + MutableColumns columns = header.cloneEmptyColumns(); + + /// It is possible to display detailed diagnostics only if the last and next to last rows are still in the read buffer. + size_t bytes_read_at_start_of_buffer = in.count() - in.offset(); + if (bytes_read_at_start_of_buffer != bytes_read_at_start_of_buffer_on_prev_row) + { + out << "Could not print diagnostic info because two last rows aren't in buffer (rare case)\n"; + return out.str(); + } + + size_t max_length_of_column_name = 0; + for (size_t i = 0; i < header.columns(); ++i) + if (header.safeGetByPosition(i).name.size() > max_length_of_column_name) + max_length_of_column_name = header.safeGetByPosition(i).name.size(); + + size_t max_length_of_data_type_name = 0; + for (size_t i = 0; i < header.columns(); ++i) + if (header.safeGetByPosition(i).type->getName().size() > max_length_of_data_type_name) + max_length_of_data_type_name = header.safeGetByPosition(i).type->getName().size(); + + /// Roll back the cursor to the beginning of the previous or current row and parse all over again. But now we derive detailed information. + + if (pos_of_prev_row) + { + in.position() = pos_of_prev_row; + + out << "\nRow " << (row_num - 1) << ":\n"; + if (!parseRowAndPrintDiagnosticInfo(columns, out, max_length_of_column_name, max_length_of_data_type_name)) + return out.str(); + } + else + { + if (!pos_of_current_row) + { + out << "Could not print diagnostic info because parsing of data hasn't started.\n"; + return out.str(); + } + + in.position() = pos_of_current_row; + } + + out << "\nRow " << row_num << ":\n"; + parseRowAndPrintDiagnosticInfo(columns, out, max_length_of_column_name, max_length_of_data_type_name); + out << "\n"; + + return out.str(); +} + + +bool CSVRowInputFormat::parseRowAndPrintDiagnosticInfo(MutableColumns & columns, + WriteBuffer & out, size_t max_length_of_column_name, size_t max_length_of_data_type_name) +{ + const char delimiter = format_settings.csv.delimiter; + auto & header = getPort().getHeader(); + + size_t size = data_types.size(); + for (size_t i = 0; i < size; ++i) + { + if (i == 0 && in.eof()) + { + out << "\n"; + return false; + } + + out << "Column " << i << ", " << std::string((i < 10 ? 2 : i < 100 ? 1 : 0), ' ') + << "name: " << header.safeGetByPosition(i).name << ", " << std::string(max_length_of_column_name - header.safeGetByPosition(i).name.size(), ' ') + << "type: " << data_types[i]->getName() << ", " << std::string(max_length_of_data_type_name - data_types[i]->getName().size(), ' '); + + BufferBase::Position prev_position = in.position(); + BufferBase::Position curr_position = in.position(); + std::exception_ptr exception; + + try + { + skipWhitespacesAndTabs(in); + prev_position = in.position(); + data_types[i]->deserializeAsTextCSV(*columns[i], in, format_settings); + curr_position = in.position(); + skipWhitespacesAndTabs(in); + } + catch (...) + { + exception = std::current_exception(); + } + + if (curr_position < prev_position) + throw Exception("Logical error: parsing is non-deterministic.", ErrorCodes::LOGICAL_ERROR); + + if (isNumber(data_types[i]) || isDateOrDateTime(data_types[i])) + { + /// An empty string instead of a value. + if (curr_position == prev_position) + { + out << "ERROR: text "; + verbosePrintString(prev_position, std::min(prev_position + 10, in.buffer().end()), out); + out << " is not like " << data_types[i]->getName() << "\n"; + return false; + } + } + + out << "parsed text: "; + verbosePrintString(prev_position, curr_position, out); + + if (exception) + { + if (data_types[i]->getName() == "DateTime") + out << "ERROR: DateTime must be in YYYY-MM-DD hh:mm:ss or NNNNNNNNNN (unix timestamp, exactly 10 digits) format.\n"; + else if (data_types[i]->getName() == "Date") + out << "ERROR: Date must be in YYYY-MM-DD format.\n"; + else + out << "ERROR\n"; + return false; + } + + out << "\n"; + + if (data_types[i]->haveMaximumSizeOfValue()) + { + if (*curr_position != '\n' && *curr_position != '\r' && *curr_position != delimiter) + { + out << "ERROR: garbage after " << data_types[i]->getName() << ": "; + verbosePrintString(curr_position, std::min(curr_position + 10, in.buffer().end()), out); + out << "\n"; + + if (data_types[i]->getName() == "DateTime") + out << "ERROR: DateTime must be in YYYY-MM-DD hh:mm:ss or NNNNNNNNNN (unix timestamp, exactly 10 digits) format.\n"; + else if (data_types[i]->getName() == "Date") + out << "ERROR: Date must be in YYYY-MM-DD format.\n"; + + return false; + } + } + + /// Delimiters + if (i + 1 == size) + { + if (in.eof()) + return false; + + /// we support the extra delimiter at the end of the line + if (*in.position() == delimiter) + { + ++in.position(); + if (in.eof()) + break; + } + + if (!in.eof() && *in.position() != '\n' && *in.position() != '\r') + { + out << "ERROR: There is no line feed. "; + verbosePrintString(in.position(), in.position() + 1, out); + out << " found instead.\n" + " It's like your file has more columns than expected.\n" + "And if your file have right number of columns, maybe it have unquoted string value with comma.\n"; + + return false; + } + + skipEndOfLine(in); + } + else + { + try + { + assertChar(delimiter, in); + } + catch (const DB::Exception &) + { + if (*in.position() == '\n' || *in.position() == '\r') + { + out << "ERROR: Line feed found where delimiter (" << delimiter << ") is expected." + " It's like your file has less columns than expected.\n" + "And if your file have right number of columns, maybe it have unescaped quotes in values.\n"; + } + else + { + out << "ERROR: There is no delimiter (" << delimiter << "). "; + verbosePrintString(in.position(), in.position() + 1, out); + out << " found instead.\n"; + } + return false; + } + } + } + + return true; +} + + +void CSVRowInputFormat::syncAfterError() +{ + skipToNextLineOrEOF(in); +} + +void CSVRowInputFormat::updateDiagnosticInfo() +{ + ++row_num; + + bytes_read_at_start_of_buffer_on_prev_row = bytes_read_at_start_of_buffer_on_current_row; + bytes_read_at_start_of_buffer_on_current_row = in.count() - in.offset(); + + pos_of_prev_row = pos_of_current_row; + pos_of_current_row = in.position(); +} + + +void registerInputFormatProcessorCSV(FormatFactory & factory) +{ + for (bool with_names : {false, true}) + { + factory.registerInputFormatProcessor(with_names ? "CSVWithNames" : "CSV", [=]( + ReadBuffer & buf, + const Block & sample, + const Context &, + IRowInputFormat::Params params, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, params, with_names, settings); + }); + } +} + +} diff --git a/dbms/src/Processors/Formats/Impl/CSVRowInputFormat.h b/dbms/src/Processors/Formats/Impl/CSVRowInputFormat.h new file mode 100644 index 00000000000..db7041bc90a --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/CSVRowInputFormat.h @@ -0,0 +1,56 @@ +#pragma once + +#include +#include +#include + + +namespace DB +{ + +class ReadBuffer; + +/** A stream for inputting data in csv format. + * Does not conform with https://tools.ietf.org/html/rfc4180 because it skips spaces and tabs between values. + */ +class CSVRowInputFormat : public IRowInputFormat +{ +public: + /** with_names - in the first line the header with column names + * with_types - on the next line header with type names + */ + CSVRowInputFormat(ReadBuffer & in_, Block header, Params params, bool with_names, const FormatSettings & format_settings); + + String getName() const override { return "CSVRowInputFormat"; } + + bool readRow(MutableColumns & columns, RowReadExtension &) override; + void readPrefix() override; + bool allowSyncAfterError() const override { return true; } + void syncAfterError() override; + + std::string getDiagnosticInfo() override; + +private: + bool with_names; + DataTypes data_types; + + const FormatSettings format_settings; + + /// For convenient diagnostics in case of an error. + + size_t row_num = 0; + + /// How many bytes were read, not counting those that are still in the buffer. + size_t bytes_read_at_start_of_buffer_on_current_row = 0; + size_t bytes_read_at_start_of_buffer_on_prev_row = 0; + + char * pos_of_current_row = nullptr; + char * pos_of_prev_row = nullptr; + + void updateDiagnosticInfo(); + + bool parseRowAndPrintDiagnosticInfo(MutableColumns & columns, + WriteBuffer & out, size_t max_length_of_column_name, size_t max_length_of_data_type_name); +}; + +} diff --git a/dbms/src/Processors/Formats/Impl/CSVRowOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/CSVRowOutputFormat.cpp new file mode 100644 index 00000000000..c5246dfb1cc --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/CSVRowOutputFormat.cpp @@ -0,0 +1,87 @@ +#include +#include + +#include + + +namespace DB +{ + + +CSVRowOutputFormat::CSVRowOutputFormat(WriteBuffer & out_, const Block & header, bool with_names_, const FormatSettings & format_settings) + : IRowOutputFormat(header, out_), with_names(with_names_), format_settings(format_settings) +{ + auto & sample = getPort(PortKind::Main).getHeader(); + size_t columns = sample.columns(); + data_types.resize(columns); + for (size_t i = 0; i < columns; ++i) + data_types[i] = sample.safeGetByPosition(i).type; +} + + +void CSVRowOutputFormat::writePrefix() +{ + auto & sample = getPort(PortKind::Main).getHeader(); + size_t columns = sample.columns(); + + if (with_names) + { + for (size_t i = 0; i < columns; ++i) + { + writeCSVString(sample.safeGetByPosition(i).name, out); + + char delimiter = format_settings.csv.delimiter; + if (i + 1 == columns) + delimiter = '\n'; + + writeChar(delimiter, out); + } + } +} + + +void CSVRowOutputFormat::writeField(const IColumn & column, const IDataType & type, size_t row_num) +{ + type.serializeAsTextCSV(column, row_num, out, format_settings); +} + + +void CSVRowOutputFormat::writeFieldDelimiter() +{ + writeChar(format_settings.csv.delimiter, out); +} + + +void CSVRowOutputFormat::writeRowEndDelimiter() +{ + writeChar('\n', out); +} + +void CSVRowOutputFormat::writeBeforeTotals() +{ + writeChar('\n', out); +} + +void CSVRowOutputFormat::writeBeforeExtremes() +{ + writeChar('\n', out); +} + + + +void registerOutputFormatProcessorCSV(FormatFactory & factory) +{ + for (bool with_names : {false, true}) + { + factory.registerOutputFormatProcessor(with_names ? "CSVWithNames" : "CSV", [=]( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & format_settings) + { + return std::make_shared(buf, sample, with_names, format_settings); + }); + } +} + +} diff --git a/dbms/src/Processors/Formats/Impl/CSVRowOutputFormat.h b/dbms/src/Processors/Formats/Impl/CSVRowOutputFormat.h new file mode 100644 index 00000000000..5593fc98455 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/CSVRowOutputFormat.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include + + +namespace DB +{ + +class WriteBuffer; + + +/** The stream for outputting data in csv format. + * Does not conform with https://tools.ietf.org/html/rfc4180 because it uses LF, not CR LF. + */ +class CSVRowOutputFormat : public IRowOutputFormat +{ +public: + /** with_names - output in the first line a header with column names + * with_types - output in the next line header with the names of the types + */ + CSVRowOutputFormat(WriteBuffer & out_, const Block & header, bool with_names_, const FormatSettings & format_settings); + + String getName() const override { return "CSVRowOutputFormat"; } + + void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; + void writeFieldDelimiter() override; + void writeRowEndDelimiter() override; + void writePrefix() override; + void writeBeforeTotals() override; + void writeBeforeExtremes() override; + + /// https://www.iana.org/assignments/media-types/text/csv + String getContentType() const override + { + return String("text/csv; charset=UTF-8; header=") + (with_names ? "present" : "absent"); + } + +protected: + + bool with_names; + const FormatSettings format_settings; + DataTypes data_types; +}; + +} + diff --git a/dbms/src/Processors/Formats/Impl/CapnProtoRowInputFormat.cpp b/dbms/src/Processors/Formats/Impl/CapnProtoRowInputFormat.cpp new file mode 100644 index 00000000000..9ed84e89780 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/CapnProtoRowInputFormat.cpp @@ -0,0 +1,314 @@ +#include "config_formats.h" +#if USE_CAPNP + +#include +#include +#include // Y_IGNORE +#include +#include +#include // Y_IGNORE +#include // Y_IGNORE +#include // Y_IGNORE +#include +#include +#include + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int BAD_TYPE_OF_FIELD; + extern const int BAD_ARGUMENTS; + extern const int THERE_IS_NO_COLUMN; + extern const int LOGICAL_ERROR; +} + +static CapnProtoRowInputFormat::NestedField split(const Block & header, size_t i) +{ + CapnProtoRowInputFormat::NestedField field = {{}, i}; + + // Remove leading dot in field definition, e.g. ".msg" -> "msg" + String name(header.safeGetByPosition(i).name); + if (!name.empty() && name[0] == '.') + name.erase(0, 1); + + boost::split(field.tokens, name, boost::is_any_of("._")); + return field; +} + + +static Field convertNodeToField(const capnp::DynamicValue::Reader & value) +{ + switch (value.getType()) + { + case capnp::DynamicValue::UNKNOWN: + throw Exception("Unknown field type", ErrorCodes::BAD_TYPE_OF_FIELD); + case capnp::DynamicValue::VOID: + return Field(); + case capnp::DynamicValue::BOOL: + return value.as() ? 1u : 0u; + case capnp::DynamicValue::INT: + return value.as(); + case capnp::DynamicValue::UINT: + return value.as(); + case capnp::DynamicValue::FLOAT: + return value.as(); + case capnp::DynamicValue::TEXT: + { + auto arr = value.as(); + return String(arr.begin(), arr.size()); + } + case capnp::DynamicValue::DATA: + { + auto arr = value.as().asChars(); + return String(arr.begin(), arr.size()); + } + case capnp::DynamicValue::LIST: + { + auto listValue = value.as(); + Array res(listValue.size()); + for (auto i : kj::indices(listValue)) + res[i] = convertNodeToField(listValue[i]); + + return res; + } + case capnp::DynamicValue::ENUM: + return value.as().getRaw(); + case capnp::DynamicValue::STRUCT: + { + auto structValue = value.as(); + const auto & fields = structValue.getSchema().getFields(); + + Field field = Tuple(TupleBackend(fields.size())); + TupleBackend & tuple = get(field).toUnderType(); + for (auto i : kj::indices(fields)) + tuple[i] = convertNodeToField(structValue.get(fields[i])); + + return field; + } + case capnp::DynamicValue::CAPABILITY: + throw Exception("CAPABILITY type not supported", ErrorCodes::BAD_TYPE_OF_FIELD); + case capnp::DynamicValue::ANY_POINTER: + throw Exception("ANY_POINTER type not supported", ErrorCodes::BAD_TYPE_OF_FIELD); + } + return Field(); +} + +static capnp::StructSchema::Field getFieldOrThrow(capnp::StructSchema node, const std::string & field) +{ + KJ_IF_MAYBE(child, node.findFieldByName(field)) + return *child; + else + throw Exception("Field " + field + " doesn't exist in schema " + node.getShortDisplayName().cStr(), ErrorCodes::THERE_IS_NO_COLUMN); +} + + +void CapnProtoRowInputFormat::createActions(const NestedFieldList & sorted_fields, capnp::StructSchema reader) +{ + /// Columns in a table can map to fields in Cap'n'Proto or to structs. + + /// Store common parents and their tokens in order to backtrack. + std::vector parents; + std::vector parent_tokens; + + capnp::StructSchema cur_reader = reader; + + for (const auto & field : sorted_fields) + { + if (field.tokens.empty()) + throw Exception("Logical error in CapnProtoRowInputFormat", ErrorCodes::LOGICAL_ERROR); + + // Backtrack to common parent + while (field.tokens.size() < parent_tokens.size() + 1 + || !std::equal(parent_tokens.begin(), parent_tokens.end(), field.tokens.begin())) + { + actions.push_back({Action::POP}); + parents.pop_back(); + parent_tokens.pop_back(); + + if (parents.empty()) + { + cur_reader = reader; + break; + } + else + cur_reader = parents.back().getType().asStruct(); + } + + // Go forward + while (parent_tokens.size() + 1 < field.tokens.size()) + { + const auto & token = field.tokens[parents.size()]; + auto node = getFieldOrThrow(cur_reader, token); + if (node.getType().isStruct()) + { + // Descend to field structure + parents.emplace_back(node); + parent_tokens.emplace_back(token); + cur_reader = node.getType().asStruct(); + actions.push_back({Action::PUSH, node}); + } + else if (node.getType().isList()) + { + break; // Collect list + } + else + throw Exception("Field " + token + " is neither Struct nor List", ErrorCodes::BAD_TYPE_OF_FIELD); + } + + // Read field from the structure + auto node = getFieldOrThrow(cur_reader, field.tokens[parents.size()]); + if (node.getType().isList() && !actions.empty() && actions.back().field == node) + { + // The field list here flattens Nested elements into multiple arrays + // In order to map Nested types in Cap'nProto back, they need to be collected + // Since the field names are sorted, the order of field positions must be preserved + // For example, if the fields are { b @0 :Text, a @1 :Text }, the `a` would come first + // even though it's position is second. + auto & columns = actions.back().columns; + auto it = std::upper_bound(columns.cbegin(), columns.cend(), field.pos); + columns.insert(it, field.pos); + } + else + { + actions.push_back({Action::READ, node, {field.pos}}); + } + } +} + +CapnProtoRowInputFormat::CapnProtoRowInputFormat(ReadBuffer & in_, Block header, Params params, const FormatSchemaInfo & info) + : IRowInputFormat(std::move(header), in_, params), parser(std::make_shared()) +{ + // Parse the schema and fetch the root object + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + auto schema = parser->impl.parseDiskFile(info.schemaPath(), info.absoluteSchemaPath(), {}); +#pragma GCC diagnostic pop + + root = schema.getNested(info.messageName()).asStruct(); + + /** + * The schema typically consists of fields in various nested structures. + * Here we gather the list of fields and sort them in a way so that fields in the same structure are adjacent, + * and the nesting level doesn't decrease to make traversal easier. + */ + auto & sample = getPort().getHeader(); + NestedFieldList list; + size_t num_columns = sample.columns(); + for (size_t i = 0; i < num_columns; ++i) + list.push_back(split(sample, i)); + + // Order list first by value of strings then by length of string vector. + std::sort(list.begin(), list.end(), [](const NestedField & a, const NestedField & b) { return a.tokens < b.tokens; }); + createActions(list, root); +} + + +bool CapnProtoRowInputFormat::readRow(MutableColumns & columns, RowReadExtension &) +{ + if (in.eof()) + return false; + + // Read from underlying buffer directly + auto buf = in.buffer(); + auto base = reinterpret_cast(in.position()); + + // Check if there's enough bytes in the buffer to read the full message + kj::Array heap_array; + auto array = kj::arrayPtr(base, buf.size() - in.offset()); + auto expected_words = capnp::expectedSizeInWordsFromPrefix(array); + if (expected_words * sizeof(capnp::word) > array.size()) + { + // We'll need to reassemble the message in a contiguous buffer + heap_array = kj::heapArray(expected_words); + in.readStrict(heap_array.asChars().begin(), heap_array.asChars().size()); + array = heap_array.asPtr(); + } + + +#if CAPNP_VERSION >= 8000 + capnp::UnalignedFlatArrayMessageReader msg(array); +#else + capnp::FlatArrayMessageReader msg(array); +#endif + std::vector stack; + stack.push_back(msg.getRoot(root)); + + for (auto action : actions) + { + switch (action.type) + { + case Action::READ: + { + Field value = convertNodeToField(stack.back().get(action.field)); + if (action.columns.size() > 1) + { + // Nested columns must be flattened into several arrays + // e.g. Array(Tuple(x ..., y ...)) -> Array(x ...), Array(y ...) + const auto & collected = DB::get(value); + size_t size = collected.size(); + // The flattened array contains an array of a part of the nested tuple + Array flattened(size); + for (size_t column_index = 0; column_index < action.columns.size(); ++column_index) + { + // Populate array with a single tuple elements + for (size_t off = 0; off < size; ++off) + { + const TupleBackend & tuple = DB::get(collected[off]).toUnderType(); + flattened[off] = tuple[column_index]; + } + auto & col = columns[action.columns[column_index]]; + col->insert(flattened); + } + } + else + { + auto & col = columns[action.columns[0]]; + col->insert(value); + } + + break; + } + case Action::POP: + stack.pop_back(); + break; + case Action::PUSH: + stack.push_back(stack.back().get(action.field).as()); + break; + } + } + + // Advance buffer position if used directly + if (heap_array.size() == 0) + { + auto parsed = (msg.getEnd() - base) * sizeof(capnp::word); + in.position() += parsed; + } + + return true; +} + +void registerInputFormatProcessorCapnProto(FormatFactory & factory) +{ + factory.registerInputFormatProcessor( + "CapnProto", + [](ReadBuffer & buf, const Block & sample, const Context & context, IRowInputFormat::Params params, const FormatSettings &) + { + return std::make_shared(buf, sample, params, FormatSchemaInfo(context, "capnp")); + }); +} + +} + +#else + +namespace DB +{ + class FormatFactory; + void registerInputFormatProcessorCapnProto(FormatFactory &) {} +} + +#endif // USE_CAPNP diff --git a/dbms/src/Processors/Formats/Impl/CapnProtoRowInputFormat.h b/dbms/src/Processors/Formats/Impl/CapnProtoRowInputFormat.h new file mode 100644 index 00000000000..8d768538719 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/CapnProtoRowInputFormat.h @@ -0,0 +1,75 @@ +#pragma once +#include +#if USE_CAPNP + +#include +#include + +#include + +namespace DB +{ + +class FormatSchemaInfo; +class ReadBuffer; + +/** A stream for reading messages in Cap'n Proto format in given schema. + * Like Protocol Buffers and Thrift (but unlike JSON or MessagePack), + * Cap'n Proto messages are strongly-typed and not self-describing. + * The schema in this case cannot be compiled in, so it uses a runtime schema parser. + * See https://capnproto.org/cxx.html + */ +class CapnProtoRowInputFormat : public IRowInputFormat +{ +public: + struct NestedField + { + std::vector tokens; + size_t pos; + }; + using NestedFieldList = std::vector; + + /** schema_dir - base path for schema files + * schema_file - location of the capnproto schema, e.g. "schema.capnp" + * root_object - name to the root object, e.g. "Message" + */ + CapnProtoRowInputFormat(ReadBuffer & in_, Block header, Params params, const FormatSchemaInfo & info); + + String getName() const override { return "CapnProtoRowInputFormat"; } + + bool readRow(MutableColumns & columns, RowReadExtension &) override; + +private: + // Build a traversal plan from a sorted list of fields + void createActions(const NestedFieldList & sortedFields, capnp::StructSchema reader); + + /* Action for state machine for traversing nested structures. */ + using BlockPositionList = std::vector; + struct Action + { + enum Type { POP, PUSH, READ }; + Type type; + capnp::StructSchema::Field field = {}; + BlockPositionList columns = {}; + }; + + // Wrapper for classes that could throw in destructor + // https://github.com/capnproto/capnproto/issues/553 + template + struct DestructorCatcher + { + T impl; + template + DestructorCatcher(Arg && ... args) : impl(kj::fwd(args)...) {} + ~DestructorCatcher() noexcept try { } catch (...) { return; } + }; + using SchemaParser = DestructorCatcher; + + std::shared_ptr parser; + capnp::StructSchema root; + std::vector actions; +}; + +} + +#endif // USE_CAPNP diff --git a/dbms/src/Processors/Formats/Impl/JSONCompactRowOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/JSONCompactRowOutputFormat.cpp new file mode 100644 index 00000000000..0f63a4cf72d --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/JSONCompactRowOutputFormat.cpp @@ -0,0 +1,92 @@ +#include +#include + +#include + + +namespace DB +{ + +JSONCompactRowOutputFormat::JSONCompactRowOutputFormat( + WriteBuffer & out_, const Block & header, const FormatSettings & settings_) + : JSONRowOutputFormat(out_, header, settings_) +{ +} + + +void JSONCompactRowOutputFormat::writeField(const IColumn & column, const IDataType & type, size_t row_num) +{ + type.serializeAsTextJSON(column, row_num, *ostr, settings); + ++field_number; +} + + +void JSONCompactRowOutputFormat::writeFieldDelimiter() +{ + writeCString(", ", *ostr); +} + +void JSONCompactRowOutputFormat::writeTotalsFieldDelimiter() +{ + writeCString(",", *ostr); +} + + +void JSONCompactRowOutputFormat::writeRowStartDelimiter() +{ + if (row_count > 0) + writeCString(",\n", *ostr); + writeCString("\t\t[", *ostr); +} + + +void JSONCompactRowOutputFormat::writeRowEndDelimiter() +{ + writeChar(']', *ostr); + field_number = 0; + ++row_count; +} + +void JSONCompactRowOutputFormat::writeBeforeTotals() +{ + writeCString(",\n", *ostr); + writeChar('\n', *ostr); + writeCString("\t\"totals\": [", *ostr); +} + +void JSONCompactRowOutputFormat::writeAfterTotals() +{ + writeChar(']', *ostr); +} + +void JSONCompactRowOutputFormat::writeExtremesElement(const char * title, const Columns & columns, size_t row_num) +{ + writeCString("\t\t\"", *ostr); + writeCString(title, *ostr); + writeCString("\": [", *ostr); + + size_t extremes_columns = columns.size(); + for (size_t i = 0; i < extremes_columns; ++i) + { + if (i != 0) + writeTotalsFieldDelimiter(); + + writeField(*columns[i], *types[i], row_num); + } + + writeChar(']', *ostr); +} + +void registerOutputFormatProcessorJSONCompact(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("JSONCompact", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & format_settings) + { + return std::make_shared(buf, sample, format_settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/JSONCompactRowOutputFormat.h b/dbms/src/Processors/Formats/Impl/JSONCompactRowOutputFormat.h new file mode 100644 index 00000000000..e2b5ce76f88 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/JSONCompactRowOutputFormat.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include +#include + + +namespace DB +{ + +struct FormatSettings; + +/** The stream for outputting data in the JSONCompact format. + */ +class JSONCompactRowOutputFormat : public JSONRowOutputFormat +{ +public: + JSONCompactRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & settings_); + + String getName() const override { return "JSONCompactRowOutputFormat"; } + + void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; + void writeFieldDelimiter() override; + void writeRowStartDelimiter() override; + void writeRowEndDelimiter() override; + + void writeBeforeTotals() override; + void writeAfterTotals() override; + +protected: + void writeExtremesElement(const char * title, const Columns & columns, size_t row_num) override; + + void writeTotalsField(const IColumn & column, const IDataType & type, size_t row_num) override + { + return writeField(column, type, row_num); + } + + void writeTotalsFieldDelimiter() override; + +}; + +} diff --git a/dbms/src/Processors/Formats/Impl/JSONEachRowRowInputFormat.cpp b/dbms/src/Processors/Formats/Impl/JSONEachRowRowInputFormat.cpp new file mode 100644 index 00000000000..b1dde6d2275 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/JSONEachRowRowInputFormat.cpp @@ -0,0 +1,270 @@ +#include + +#include +#include +#include + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int INCORRECT_DATA; + extern const int CANNOT_READ_ALL_DATA; + extern const int LOGICAL_ERROR; +} + +namespace +{ + +enum +{ + UNKNOWN_FIELD = size_t(-1), + NESTED_FIELD = size_t(-2) +}; + +} + + +JSONEachRowRowInputFormat::JSONEachRowRowInputFormat( + ReadBuffer & in_, const Block & header, Params params, const FormatSettings & format_settings) + : IRowInputFormat(header, in_, params), format_settings(format_settings), name_map(header.columns()) +{ + /// In this format, BOM at beginning of stream cannot be confused with value, so it is safe to skip it. + skipBOMIfExists(in); + + size_t num_columns = getPort().getHeader().columns(); + for (size_t i = 0; i < num_columns; ++i) + { + const String & column_name = columnName(i); + name_map[column_name] = i; /// NOTE You could place names more cache-locally. + if (format_settings.import_nested_json) + { + const auto splitted = Nested::splitName(column_name); + if (!splitted.second.empty()) + { + const StringRef table_name(column_name.data(), splitted.first.size()); + name_map[table_name] = NESTED_FIELD; + } + } + } + + prev_positions.assign(num_columns, name_map.end()); +} + +const String & JSONEachRowRowInputFormat::columnName(size_t i) const +{ + return getPort().getHeader().getByPosition(i).name; +} + +inline size_t JSONEachRowRowInputFormat::columnIndex(const StringRef & name, size_t key_index) +{ + /// Optimization by caching the order of fields (which is almost always the same) + /// and a quick check to match the next expected field, instead of searching the hash table. + + if (prev_positions.size() > key_index + && prev_positions[key_index] != name_map.end() + && name == prev_positions[key_index]->getFirst()) + { + return prev_positions[key_index]->getSecond(); + } + else + { + const auto it = name_map.find(name); + + if (name_map.end() != it) + { + if (key_index < prev_positions.size()) + prev_positions[key_index] = it; + + return it->getSecond(); + } + else + return UNKNOWN_FIELD; + } +} + +/** Read the field name and convert it to column name + * (taking into account the current nested name prefix) + * Resulting StringRef is valid only before next read from buf. + */ +StringRef JSONEachRowRowInputFormat::readColumnName(ReadBuffer & buf) +{ + // This is just an optimization: try to avoid copying the name into current_column_name + + if (nested_prefix_length == 0 && buf.position() + 1 < buf.buffer().end()) + { + char * next_pos = find_first_symbols<'\\', '"'>(buf.position() + 1, buf.buffer().end()); + + if (next_pos != buf.buffer().end() && *next_pos != '\\') + { + /// The most likely option is that there is no escape sequence in the key name, and the entire name is placed in the buffer. + assertChar('"', buf); + StringRef res(buf.position(), next_pos - buf.position()); + buf.position() = next_pos + 1; + return res; + } + } + + current_column_name.resize(nested_prefix_length); + readJSONStringInto(current_column_name, buf); + return current_column_name; +} + + +static inline void skipColonDelimeter(ReadBuffer & istr) +{ + skipWhitespaceIfAny(istr); + assertChar(':', istr); + skipWhitespaceIfAny(istr); +} + +void JSONEachRowRowInputFormat::skipUnknownField(const StringRef & name_ref) +{ + if (!format_settings.skip_unknown_fields) + throw Exception("Unknown field found while parsing JSONEachRow format: " + name_ref.toString(), ErrorCodes::INCORRECT_DATA); + + skipJSONField(in, name_ref); +} + +void JSONEachRowRowInputFormat::readField(size_t index, MutableColumns & columns) +{ + if (read_columns[index]) + throw Exception("Duplicate field found while parsing JSONEachRow format: " + columnName(index), ErrorCodes::INCORRECT_DATA); + + try + { + auto & header = getPort().getHeader(); + header.getByPosition(index).type->deserializeAsTextJSON(*columns[index], in, format_settings); + } + catch (Exception & e) + { + e.addMessage("(while read the value of key " + columnName(index) + ")"); + throw; + } + + read_columns[index] = true; +} + +inline bool JSONEachRowRowInputFormat::advanceToNextKey(size_t key_index) +{ + skipWhitespaceIfAny(in); + + if (in.eof()) + throw Exception("Unexpected end of stream while parsing JSONEachRow format", ErrorCodes::CANNOT_READ_ALL_DATA); + else if (*in.position() == '}') + { + ++in.position(); + return false; + } + + if (key_index > 0) + { + assertChar(',', in); + skipWhitespaceIfAny(in); + } + return true; +} + +void JSONEachRowRowInputFormat::readJSONObject(MutableColumns & columns) +{ + assertChar('{', in); + + for (size_t key_index = 0; advanceToNextKey(key_index); ++key_index) + { + StringRef name_ref = readColumnName(in); + const size_t column_index = columnIndex(name_ref, key_index); + + if (unlikely(ssize_t(column_index) < 0)) + { + /// name_ref may point directly to the input buffer + /// and input buffer may be filled with new data on next read + /// If we want to use name_ref after another reads from buffer, we must copy it to temporary string. + + current_column_name.assign(name_ref.data, name_ref.size); + name_ref = StringRef(current_column_name); + + skipColonDelimeter(in); + + if (column_index == UNKNOWN_FIELD) + skipUnknownField(name_ref); + else if (column_index == NESTED_FIELD) + readNestedData(name_ref.toString(), columns); + else + throw Exception("Logical error: illegal value of column_index", ErrorCodes::LOGICAL_ERROR); + } + else + { + skipColonDelimeter(in); + readField(column_index, columns); + } + } +} + +void JSONEachRowRowInputFormat::readNestedData(const String & name, MutableColumns & columns) +{ + current_column_name = name; + current_column_name.push_back('.'); + nested_prefix_length = current_column_name.size(); + readJSONObject(columns); + nested_prefix_length = 0; +} + + +bool JSONEachRowRowInputFormat::readRow(MutableColumns & columns, RowReadExtension & ext) +{ + skipWhitespaceIfAny(in); + + /// We consume ;, or \n before scanning a new row, instead scanning to next row at the end. + /// The reason is that if we want an exact number of rows read with LIMIT x + /// from a streaming table engine with text data format, like File or Kafka + /// then seeking to next ;, or \n would trigger reading of an extra row at the end. + + /// Semicolon is added for convenience as it could be used at end of INSERT query. + if (!in.eof() && (*in.position() == ',' || *in.position() == ';')) + ++in.position(); + + skipWhitespaceIfAny(in); + if (in.eof()) + return false; + + size_t num_columns = columns.size(); + + /// Set of columns for which the values were read. The rest will be filled with default values. + read_columns.assign(num_columns, false); + + nested_prefix_length = 0; + readJSONObject(columns); + + auto & header = getPort().getHeader(); + /// Fill non-visited columns with the default values. + for (size_t i = 0; i < num_columns; ++i) + if (!read_columns[i]) + header.getByPosition(i).type->insertDefaultInto(*columns[i]); + + /// return info about defaults set + ext.read_columns = read_columns; + return true; +} + + +void JSONEachRowRowInputFormat::syncAfterError() +{ + skipToUnescapedNextLineOrEOF(in); +} + + +void registerInputFormatProcessorJSONEachRow(FormatFactory & factory) +{ + factory.registerInputFormatProcessor("JSONEachRow", []( + ReadBuffer & buf, + const Block & sample, + const Context &, + IRowInputFormat::Params params, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, params, settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/JSONEachRowRowInputFormat.h b/dbms/src/Processors/Formats/Impl/JSONEachRowRowInputFormat.h new file mode 100644 index 00000000000..901e35af6e8 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/JSONEachRowRowInputFormat.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include +#include + + +namespace DB +{ + +class ReadBuffer; + + +/** A stream for reading data in JSON format, where each row is represented by a separate JSON object. + * Objects can be separated by feed return, other whitespace characters in any number and possibly a comma. + * Fields can be listed in any order (including, in different lines there may be different order), + * and some fields may be missing. + */ +class JSONEachRowRowInputFormat : public IRowInputFormat +{ +public: + JSONEachRowRowInputFormat(ReadBuffer & in_, const Block & header, Params params, const FormatSettings & format_settings); + + String getName() const override { return "JSONEachRowRowInputFormat"; } + + bool readRow(MutableColumns & columns, RowReadExtension & ext) override; + bool allowSyncAfterError() const override { return true; } + void syncAfterError() override; + +private: + const String & columnName(size_t i) const; + size_t columnIndex(const StringRef & name, size_t key_index); + bool advanceToNextKey(size_t key_index); + void skipUnknownField(const StringRef & name_ref); + StringRef readColumnName(ReadBuffer & buf); + void readField(size_t index, MutableColumns & columns); + void readJSONObject(MutableColumns & columns); + void readNestedData(const String & name, MutableColumns & columns); + +private: + + const FormatSettings format_settings; + + /// Buffer for the read from the stream field name. Used when you have to copy it. + /// Also, if processing of Nested data is in progress, it holds the common prefix + /// of the nested column names (so that appending the field name to it produces + /// the full column name) + String current_column_name; + + /// If processing Nested data, holds the length of the common prefix + /// of the names of related nested columns. For example, for a table + /// created as follows + /// CREATE TABLE t (n Nested (i Int32, s String)) + /// the nested column names are 'n.i' and 'n.s' and the nested prefix is 'n.' + size_t nested_prefix_length = 0; + + std::vector read_columns; + + /// Hash table match `field name -> position in the block`. NOTE You can use perfect hash map. + using NameMap = HashMap; + NameMap name_map; + + /// Cached search results for previous row (keyed as index in JSON object) - used as a hint. + std::vector prev_positions; +}; + +} diff --git a/dbms/src/Processors/Formats/Impl/JSONEachRowRowOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/JSONEachRowRowOutputFormat.cpp new file mode 100644 index 00000000000..112021dce42 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/JSONEachRowRowOutputFormat.cpp @@ -0,0 +1,66 @@ +#include +#include +#include +#include + + +namespace DB +{ + + +JSONEachRowRowOutputFormat::JSONEachRowRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & settings) + : IRowOutputFormat(header, out_), settings(settings) +{ + auto & sample = getPort(PortKind::Main).getHeader(); + size_t columns = sample.columns(); + fields.resize(columns); + + for (size_t i = 0; i < columns; ++i) + { + WriteBufferFromString buf(fields[i]); + writeJSONString(sample.getByPosition(i).name, buf, settings); + } +} + + +void JSONEachRowRowOutputFormat::writeField(const IColumn & column, const IDataType & type, size_t row_num) +{ + writeString(fields[field_number], out); + writeChar(':', out); + type.serializeAsTextJSON(column, row_num, out, settings); + ++field_number; +} + + +void JSONEachRowRowOutputFormat::writeFieldDelimiter() +{ + writeChar(',', out); +} + + +void JSONEachRowRowOutputFormat::writeRowStartDelimiter() +{ + writeChar('{', out); +} + + +void JSONEachRowRowOutputFormat::writeRowEndDelimiter() +{ + writeCString("}\n", out); + field_number = 0; +} + + +void registerOutputFormatProcessorJSONEachRow(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("JSONEachRow", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & format_settings) + { + return std::make_shared(buf, sample, format_settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/JSONEachRowRowOutputFormat.h b/dbms/src/Processors/Formats/Impl/JSONEachRowRowOutputFormat.h new file mode 100644 index 00000000000..0ceeb5352c7 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/JSONEachRowRowOutputFormat.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include + + +namespace DB +{ + +/** The stream for outputting data in JSON format, by object per line. + * Does not validate UTF-8. + */ +class JSONEachRowRowOutputFormat : public IRowOutputFormat +{ +public: + JSONEachRowRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & settings); + + String getName() const override { return "JSONEachRowRowOutputFormat"; } + + void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; + void writeFieldDelimiter() override; + void writeRowStartDelimiter() override; + void writeRowEndDelimiter() override; + +private: + size_t field_number = 0; + Names fields; + + FormatSettings settings; +}; + +} + diff --git a/dbms/src/Processors/Formats/Impl/JSONRowOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/JSONRowOutputFormat.cpp new file mode 100644 index 00000000000..f0d791a6554 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/JSONRowOutputFormat.cpp @@ -0,0 +1,257 @@ +#include +#include +#include +#include +#include + + +namespace DB +{ + +JSONRowOutputFormat::JSONRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & settings_) + : IRowOutputFormat(header, out_), settings(settings_) +{ + auto & sample = getPort(PortKind::Main).getHeader(); + NamesAndTypesList columns(sample.getNamesAndTypesList()); + fields.assign(columns.begin(), columns.end()); + + bool need_validate_utf8 = false; + for (size_t i = 0; i < sample.columns(); ++i) + { + if (!sample.getByPosition(i).type->textCanContainOnlyValidUTF8()) + need_validate_utf8 = true; + + WriteBufferFromOwnString buf; + writeJSONString(fields[i].name, buf, settings); + + fields[i].name = buf.str(); + } + + if (need_validate_utf8) + { + validating_ostr = std::make_unique(out); + ostr = validating_ostr.get(); + } + else + ostr = &out; +} + + +void JSONRowOutputFormat::writePrefix() +{ + writeCString("{\n", *ostr); + writeCString("\t\"meta\":\n", *ostr); + writeCString("\t[\n", *ostr); + + for (size_t i = 0; i < fields.size(); ++i) + { + writeCString("\t\t{\n", *ostr); + + writeCString("\t\t\t\"name\": ", *ostr); + writeString(fields[i].name, *ostr); + writeCString(",\n", *ostr); + writeCString("\t\t\t\"type\": ", *ostr); + writeJSONString(fields[i].type->getName(), *ostr, settings); + writeChar('\n', *ostr); + + writeCString("\t\t}", *ostr); + if (i + 1 < fields.size()) + writeChar(',', *ostr); + writeChar('\n', *ostr); + } + + writeCString("\t],\n", *ostr); + writeChar('\n', *ostr); + writeCString("\t\"data\":\n", *ostr); + writeCString("\t[\n", *ostr); +} + + +void JSONRowOutputFormat::writeField(const IColumn & column, const IDataType & type, size_t row_num) +{ + writeCString("\t\t\t", *ostr); + writeString(fields[field_number].name, *ostr); + writeCString(": ", *ostr); + type.serializeAsTextJSON(column, row_num, *ostr, settings); + ++field_number; +} + +void JSONRowOutputFormat::writeTotalsField(const IColumn & column, const IDataType & type, size_t row_num) +{ + writeCString("\t\t", *ostr); + writeString(fields[field_number].name, *ostr); + writeCString(": ", *ostr); + type.serializeAsTextJSON(column, row_num, *ostr, settings); + ++field_number; +} + +void JSONRowOutputFormat::writeFieldDelimiter() +{ + writeCString(",\n", *ostr); +} + + +void JSONRowOutputFormat::writeRowStartDelimiter() +{ + writeCString("\t\t{\n", *ostr); +} + + +void JSONRowOutputFormat::writeRowEndDelimiter() +{ + writeChar('\n', *ostr); + writeCString("\t\t}", *ostr); + field_number = 0; + ++row_count; +} + + +void JSONRowOutputFormat::writeRowBetweenDelimiter() +{ + writeCString(",\n", *ostr); +} + + +void JSONRowOutputFormat::writeSuffix() +{ + writeChar('\n', *ostr); + writeCString("\t]", *ostr); +} + +void JSONRowOutputFormat::writeBeforeTotals() +{ + writeCString(",\n", *ostr); + writeChar('\n', *ostr); + writeCString("\t\"totals\":\n", *ostr); + writeCString("\t{\n", *ostr); +} + +void JSONRowOutputFormat::writeTotals(const Columns & columns, size_t row_num) +{ + size_t num_columns = columns.size(); + + for (size_t i = 0; i < num_columns; ++i) + { + if (i != 0) + writeTotalsFieldDelimiter(); + + writeTotalsField(*columns[i], *types[i], row_num); + } +} + +void JSONRowOutputFormat::writeAfterTotals() +{ + writeChar('\n', *ostr); + writeCString("\t}", *ostr); + field_number = 0; +} + +void JSONRowOutputFormat::writeBeforeExtremes() +{ + writeCString(",\n", *ostr); + writeChar('\n', *ostr); + writeCString("\t\"extremes\":\n", *ostr); + writeCString("\t{\n", *ostr); +} + +void JSONRowOutputFormat::writeExtremesElement(const char * title, const Columns & columns, size_t row_num) +{ + writeCString("\t\t\"", *ostr); + writeCString(title, *ostr); + writeCString("\":\n", *ostr); + writeCString("\t\t{\n", *ostr); + + size_t extremes_columns = columns.size(); + for (size_t i = 0; i < extremes_columns; ++i) + { + if (i != 0) + writeFieldDelimiter(); + + writeField(*columns[i], *types[i], row_num); + } + + writeChar('\n', *ostr); + writeCString("\t\t}", *ostr); + field_number = 0; +} + +void JSONRowOutputFormat::writeMinExtreme(const Columns & columns, size_t row_num) +{ + writeExtremesElement("min", columns, row_num); +} + +void JSONRowOutputFormat::writeMaxExtreme(const Columns & columns, size_t row_num) +{ + writeExtremesElement("max", columns, row_num); +} + +void JSONRowOutputFormat::writeAfterExtremes() +{ + writeChar('\n', *ostr); + writeCString("\t}", *ostr); +} + +void JSONRowOutputFormat::writeLastSuffix() +{ + writeCString(",\n\n", *ostr); + writeCString("\t\"rows\": ", *ostr); + writeIntText(row_count, *ostr); + + writeRowsBeforeLimitAtLeast(); + + if (settings.write_statistics) + writeStatistics(); + + writeChar('\n', *ostr); + writeCString("}\n", *ostr); + ostr->next(); +} + +void JSONRowOutputFormat::writeRowsBeforeLimitAtLeast() +{ + if (applied_limit) + { + writeCString(",\n\n", *ostr); + writeCString("\t\"rows_before_limit_at_least\": ", *ostr); + writeIntText(rows_before_limit, *ostr); + } +} + +void JSONRowOutputFormat::writeStatistics() +{ + writeCString(",\n\n", *ostr); + writeCString("\t\"statistics\":\n", *ostr); + writeCString("\t{\n", *ostr); + + writeCString("\t\t\"elapsed\": ", *ostr); + writeText(watch.elapsedSeconds(), *ostr); + writeCString(",\n", *ostr); + writeCString("\t\t\"rows_read\": ", *ostr); + writeText(progress.read_rows.load(), *ostr); + writeCString(",\n", *ostr); + writeCString("\t\t\"bytes_read\": ", *ostr); + writeText(progress.read_bytes.load(), *ostr); + writeChar('\n', *ostr); + + writeCString("\t}", *ostr); +} + +void JSONRowOutputFormat::onProgress(const Progress & value) +{ + progress.incrementPiecewiseAtomically(value); +} + + +void registerOutputFormatProcessorJSON(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("JSON", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & format_settings) + { + return std::make_shared(buf, sample, format_settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/JSONRowOutputFormat.h b/dbms/src/Processors/Formats/Impl/JSONRowOutputFormat.h new file mode 100644 index 00000000000..5df98475ea3 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/JSONRowOutputFormat.h @@ -0,0 +1,84 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +/** Stream for output data in JSON format. + */ +class JSONRowOutputFormat : public IRowOutputFormat +{ +public: + JSONRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & settings_); + + String getName() const override { return "JSONRowOutputFormat"; } + + void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; + void writeFieldDelimiter() override; + void writeRowStartDelimiter() override; + void writeRowEndDelimiter() override; + void writeRowBetweenDelimiter() override; + void writePrefix() override; + void writeSuffix() override; + + void writeMinExtreme(const Columns & columns, size_t row_num) override; + void writeMaxExtreme(const Columns & columns, size_t row_num) override; + void writeTotals(const Columns & columns, size_t row_num) override; + + void writeBeforeTotals() override; + void writeAfterTotals() override; + void writeBeforeExtremes() override; + void writeAfterExtremes() override; + + void writeLastSuffix() override; + + void flush() override + { + ostr->next(); + + if (validating_ostr) + out.next(); + } + + void setRowsBeforeLimit(size_t rows_before_limit_) override + { + applied_limit = true; + rows_before_limit = rows_before_limit_; + } + + void onProgress(const Progress & value) override; + + String getContentType() const override { return "application/json; charset=UTF-8"; } + +protected: + virtual void writeTotalsField(const IColumn & column, const IDataType & type, size_t row_num); + virtual void writeExtremesElement(const char * title, const Columns & columns, size_t row_num); + virtual void writeTotalsFieldDelimiter() { writeFieldDelimiter(); } + + void writeRowsBeforeLimitAtLeast(); + void writeStatistics(); + + + std::unique_ptr validating_ostr; /// Validates UTF-8 sequences, replaces bad sequences with replacement character. + WriteBuffer * ostr; + + size_t field_number = 0; + size_t row_count = 0; + bool applied_limit = false; + size_t rows_before_limit = 0; + NamesAndTypes fields; + + Progress progress; + Stopwatch watch; + FormatSettings settings; +}; + +} + diff --git a/dbms/src/Processors/Formats/Impl/MySQLOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/MySQLOutputFormat.cpp new file mode 100644 index 00000000000..4dc4a32c672 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/MySQLOutputFormat.cpp @@ -0,0 +1,105 @@ +#include + +#include +#include +#include +#include + +#include +#include + +namespace DB +{ + +using namespace MySQLProtocol; + + +MySQLOutputFormat::MySQLOutputFormat(WriteBuffer & out_, const Block & header, const Context & context, const FormatSettings & settings) + : IOutputFormat(header, out_) + , context(context) + , packet_sender(std::make_shared(out, const_cast(context.sequence_id))) /// TODO: fix it + , format_settings(settings) +{ +} + +void MySQLOutputFormat::consume(Chunk chunk) +{ + auto & header = getPort(PortKind::Main).getHeader(); + + if (!initialized) + { + initialized = true; + + + if (header.columns()) + { + + packet_sender->sendPacket(LengthEncodedNumber(header.columns())); + + for (const ColumnWithTypeAndName & column : header.getColumnsWithTypeAndName()) + { + ColumnDefinition column_definition(column.name, CharacterSet::binary, 0, ColumnType::MYSQL_TYPE_STRING, + 0, 0); + packet_sender->sendPacket(column_definition); + } + + if (!(context.client_capabilities & Capability::CLIENT_DEPRECATE_EOF)) + { + packet_sender->sendPacket(EOF_Packet(0, 0)); + } + } + } + + size_t rows = chunk.getNumRows(); + auto & columns = chunk.getColumns(); + + for (size_t i = 0; i < rows; i++) + { + ResultsetRow row_packet; + for (size_t col = 0; col < columns.size(); ++col) + { + String column_value; + WriteBufferFromString ostr(column_value); + header.getByPosition(col).type->serializeAsText(*columns[col], i, ostr, format_settings); + ostr.finish(); + + row_packet.appendColumn(std::move(column_value)); + } + packet_sender->sendPacket(row_packet); + } +} + +void MySQLOutputFormat::finalize() +{ + QueryStatus * process_list_elem = context.getProcessListElement(); + CurrentThread::finalizePerformanceCounters(); + QueryStatusInfo info = process_list_elem->getInfo(); + size_t affected_rows = info.written_rows; + + std::stringstream human_readable_info; + human_readable_info << std::fixed << std::setprecision(3) + << "Read " << info.read_rows << " rows, " << formatReadableSizeWithBinarySuffix(info.read_bytes) << " in " << info.elapsed_seconds << " sec., " + << static_cast(info.read_rows / info.elapsed_seconds) << " rows/sec., " + << formatReadableSizeWithBinarySuffix(info.read_bytes / info.elapsed_seconds) << "/sec."; + + auto & header = getPort(PortKind::Main).getHeader(); + + if (header.columns() == 0) + packet_sender->sendPacket(OK_Packet(0x0, context.client_capabilities, affected_rows, 0, 0, "", human_readable_info.str()), true); + else + if (context.client_capabilities & CLIENT_DEPRECATE_EOF) + packet_sender->sendPacket(OK_Packet(0xfe, context.client_capabilities, affected_rows, 0, 0, "", human_readable_info.str()), true); + else + packet_sender->sendPacket(EOF_Packet(0, 0), true); +} + +void registerOutputFormatProcessorMySQLWrite(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor( + "MySQLWire", [](WriteBuffer & buf, const Block & sample, const Context & context, const FormatSettings & settings) + { + return std::make_shared(buf, sample, context, settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/MySQLOutputFormat.h b/dbms/src/Processors/Formats/Impl/MySQLOutputFormat.h new file mode 100644 index 00000000000..b959342ca4d --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/MySQLOutputFormat.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#include +#include + +namespace DB +{ + +class IColumn; +class IDataType; +class WriteBuffer; +class Context; + +/** A stream for outputting data in a binary line-by-line format. + */ +class MySQLOutputFormat: public IOutputFormat +{ +public: + MySQLOutputFormat(WriteBuffer & out_, const Block & header, const Context & context, const FormatSettings & settings); + + String getName() const override { return "MySQLOutputFormat"; } + + void consume(Chunk) override; + void finalize() override; + +private: + + bool initialized = false; + + const Context & context; + std::shared_ptr packet_sender; + FormatSettings format_settings; +}; + +} + diff --git a/dbms/src/Processors/Formats/Impl/NativeFormat.cpp b/dbms/src/Processors/Formats/Impl/NativeFormat.cpp new file mode 100644 index 00000000000..0abab1e964d --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/NativeFormat.cpp @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include + + +namespace DB +{ + +class NativeInputFormatFromNativeBlockInputStream : public IInputFormat +{ +public: + NativeInputFormatFromNativeBlockInputStream(const Block & header, ReadBuffer & in_) + : IInputFormat(header, in_) + , stream(std::make_shared(in, header, 0)) + { + } + + String getName() const override { return "NativeInputFormatFromNativeBlockInputStream"; } + +protected: + Chunk generate() override + { + /// TODO: do something with totals and extremes. + + if (!read_prefix) + { + stream->readPrefix(); + read_prefix = true; + } + + auto block = stream->read(); + if (!block) + { + if (!read_suffix) + { + stream->readSuffix(); + read_suffix = true; + } + + return Chunk(); + } + + assertBlocksHaveEqualStructure(getPort().getHeader(), block, getName()); + block.checkNumberOfRows(); + + UInt64 num_rows = block.rows(); + return Chunk(block.getColumns(), num_rows); + } + +private: + std::shared_ptr stream; + bool read_prefix = false; + bool read_suffix = false; +}; + + +class NativeOutputFormatFromNativeBlockOutputStream : public IOutputFormat +{ +public: + NativeOutputFormatFromNativeBlockOutputStream(const Block & header, WriteBuffer & out_) + : IOutputFormat(header, out_) + , stream(std::make_shared(out, 0, header)) + { + } + + String getName() const override { return "NativeOutputFormatFromNativeBlockOutputStream"; } + + void setRowsBeforeLimit(size_t rows_before_limit) override + { + stream->setRowsBeforeLimit(rows_before_limit); + } + + void onProgress(const Progress & progress) override + { + stream->onProgress(progress); + } + + std::string getContentType() const override + { + return stream->getContentType(); + } + +protected: + void consume(Chunk chunk) override + { + writePrefixIfNot(); + + if (chunk) + { + + auto block = getPort(PortKind::Main).getHeader(); + block.setColumns(chunk.detachColumns()); + stream->write(block); + } + } + + void consumeTotals(Chunk chunk) override + { + writePrefixIfNot(); + + auto block = getPort(PortKind::Totals).getHeader(); + block.setColumns(chunk.detachColumns()); + stream->setTotals(block); + } + + void consumeExtremes(Chunk chunk) override + { + writePrefixIfNot(); + + auto block = getPort(PortKind::Extremes).getHeader(); + block.setColumns(chunk.detachColumns()); + stream->setExtremes(block); + } + + void finalize() override + { + writePrefixIfNot(); + writeSuffixIfNot(); + } + +private: + std::shared_ptr stream; + bool prefix_written = false; + bool suffix_written = false; + + void writePrefixIfNot() + { + if (!prefix_written) + stream->writePrefix(); + + prefix_written = true; + } + + void writeSuffixIfNot() + { + if (!suffix_written) + stream->writeSuffix(); + + suffix_written = true; + } +}; + +void registerInputFormatProcessorNative(FormatFactory & factory) +{ + factory.registerInputFormatProcessor("Native", []( + ReadBuffer & buf, + const Block & sample, + const Context &, + const RowInputFormatParams &, + const FormatSettings &) + { + return std::make_shared(sample, buf); + }); +} + +void registerOutputFormatProcessorNative(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("Native", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings &) + { + return std::make_shared(sample, buf); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/NullFormat.cpp b/dbms/src/Processors/Formats/Impl/NullFormat.cpp new file mode 100644 index 00000000000..be754294c45 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/NullFormat.cpp @@ -0,0 +1,31 @@ +#include +#include + + +namespace DB +{ + +class NullOutputFormat : public IOutputFormat +{ +public: + NullOutputFormat(const Block & header, WriteBuffer & out_) : IOutputFormat(header, out_) {} + + String getName() const override { return "NullOutputFormat"; } + +protected: + void consume(Chunk) override {} +}; + +void registerOutputFormatProcessorNull(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("Null", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings &) + { + return std::make_shared(sample, buf); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/ODBCDriver2BlockOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/ODBCDriver2BlockOutputFormat.cpp new file mode 100644 index 00000000000..543edade0e8 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ODBCDriver2BlockOutputFormat.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include + + +#include + + +namespace DB +{ +ODBCDriver2BlockOutputFormat::ODBCDriver2BlockOutputFormat( + WriteBuffer & out_, const Block & header, const FormatSettings & format_settings) + : IOutputFormat(header, out_), format_settings(format_settings) +{ +} + +static void writeODBCString(WriteBuffer & out, const std::string & str) +{ + writeIntBinary(Int32(str.size()), out); + out.write(str.data(), str.size()); +} + +void ODBCDriver2BlockOutputFormat::writeRow(const Block & header, const Columns & columns, size_t row_idx, std::string & buffer) +{ + size_t num_columns = columns.size(); + for (size_t column_idx = 0; column_idx < num_columns; ++column_idx) + { + buffer.clear(); + auto & column = columns[column_idx]; + + if (column->isNullAt(row_idx)) + { + writeIntBinary(Int32(-1), out); + } + else + { + { + WriteBufferFromString text_out(buffer); + header.getByPosition(row_idx).type->serializeAsText(*column, row_idx, text_out, format_settings); + } + writeODBCString(out, buffer); + } + } +} + +void ODBCDriver2BlockOutputFormat::write(Chunk chunk, PortKind port_kind) +{ + String text_value; + auto & header = getPort(port_kind).getHeader(); + auto & columns = chunk.getColumns(); + const size_t rows = chunk.getNumRows(); + for (size_t i = 0; i < rows; ++i) + writeRow(header, columns, i, text_value); +} + +void ODBCDriver2BlockOutputFormat::consume(Chunk chunk) +{ + writePrefixIfNot(); + write(std::move(chunk), PortKind::Main); +} + +void ODBCDriver2BlockOutputFormat::consumeTotals(Chunk chunk) +{ + writePrefixIfNot(); + write(std::move(chunk), PortKind::Totals); +} + +void ODBCDriver2BlockOutputFormat::finalize() +{ + writePrefixIfNot(); +} + +void ODBCDriver2BlockOutputFormat::writePrefix() +{ + auto & header = getPort(PortKind::Main).getHeader(); + const size_t columns = header.columns(); + + /// Number of header rows. + writeIntBinary(Int32(2), out); + + /// Names of columns. + /// Number of columns + 1 for first name column. + writeIntBinary(Int32(columns + 1), out); + writeODBCString(out, "name"); + for (size_t i = 0; i < columns; ++i) + { + const ColumnWithTypeAndName & col = header.getByPosition(i); + writeODBCString(out, col.name); + } + + /// Types of columns. + writeIntBinary(Int32(columns + 1), out); + writeODBCString(out, "type"); + for (size_t i = 0; i < columns; ++i) + { + const ColumnWithTypeAndName & col = header.getByPosition(i); + writeODBCString(out, col.type->getName()); + } +} + + +void registerOutputFormatProcessorODBCDriver2(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor( + "ODBCDriver2", [](WriteBuffer & buf, const Block & sample, const Context &, const FormatSettings & format_settings) + { + return std::make_shared(buf, sample, format_settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/ODBCDriver2BlockOutputFormat.h b/dbms/src/Processors/Formats/Impl/ODBCDriver2BlockOutputFormat.h new file mode 100644 index 00000000000..5a6ed4efc09 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ODBCDriver2BlockOutputFormat.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include +#include + + +namespace DB +{ +class WriteBuffer; + + +/** A data format designed to simplify the implementation of the ODBC driver. + * ODBC driver is designed to be build for different platforms without dependencies from the main code, + * so the format is made that way so that it can be as easy as possible to parse it. + * A header is displayed with the required information. + * The data is then output in the order of the rows. Each value is displayed as follows: length in Int32 format (-1 for NULL), then data in text form. + */ +class ODBCDriver2BlockOutputFormat final : public IOutputFormat +{ +public: + ODBCDriver2BlockOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings); + + String getName() const override { return "ODBCDriver2BlockOutputFormat"; } + + void consume(Chunk) override; + void consumeTotals(Chunk) override; + void finalize() override; + + std::string getContentType() const override + { + return "application/octet-stream"; + } + +private: + const FormatSettings format_settings; + bool prefix_written = false; + + void writePrefixIfNot() + { + if (!prefix_written) + writePrefix(); + + prefix_written = true; + } + + void writeRow(const Block & header, const Columns & columns, size_t row_idx, std::string & buffer); + void write(Chunk chunk, PortKind port_kind); + void writePrefix(); +}; + + + +} diff --git a/dbms/src/Processors/Formats/Impl/ODBCDriverBlockOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/ODBCDriverBlockOutputFormat.cpp new file mode 100644 index 00000000000..fc8796c8799 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ODBCDriverBlockOutputFormat.cpp @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include + + +namespace DB +{ + +ODBCDriverBlockOutputFormat::ODBCDriverBlockOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings) + : IOutputFormat(header, out_), format_settings(format_settings) +{ +} + +void ODBCDriverBlockOutputFormat::consume(Chunk chunk) +{ + writePrefixIfNot(); + + const size_t num_rows = chunk.getNumRows(); + const size_t num_columns = chunk.getNumColumns(); + auto & columns = chunk.getColumns(); + auto & header = getPort(PortKind::Main).getHeader(); + String text_value; + + for (size_t i = 0; i < num_rows; ++i) + { + for (size_t j = 0; j < num_columns; ++j) + { + text_value.resize(0); + auto & column = columns[j]; + auto & type = header.getByPosition(j).type; + + { + WriteBufferFromString text_out(text_value); + type->serializeAsText(*column, i, text_out, format_settings); + } + + writeStringBinary(text_value, out); + } + } +} + +void ODBCDriverBlockOutputFormat::writePrefix() +{ + auto & header = getPort(PortKind::Main).getHeader(); + const size_t columns = header.columns(); + + /// Number of columns. + writeVarUInt(columns, out); + + /// Names and types of columns. + for (size_t i = 0; i < columns; ++i) + { + const ColumnWithTypeAndName & col = header.getByPosition(i); + + writeStringBinary(col.name, out); + writeStringBinary(col.type->getName(), out); + } +} + +void ODBCDriverBlockOutputFormat::finalize() +{ + writePrefixIfNot(); +} + +void registerOutputFormatProcessorODBCDriver(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("ODBCDriver", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & format_settings) + { + return std::make_shared(buf, sample, format_settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/ODBCDriverBlockOutputFormat.h b/dbms/src/Processors/Formats/Impl/ODBCDriverBlockOutputFormat.h new file mode 100644 index 00000000000..3a0e6e29c40 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ODBCDriverBlockOutputFormat.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include + + +namespace DB +{ + +class WriteBuffer; + + +/** A data format designed to simplify the implementation of the ODBC driver. + * ODBC driver is designed to be build for different platforms without dependencies from the main code, + * so the format is made that way so that it can be as easy as possible to parse it. + * A header is displayed with the required information. + * The data is then output in the order of the rows. Each value is displayed as follows: length in VarUInt format, then data in text form. + */ +class ODBCDriverBlockOutputFormat : public IOutputFormat +{ +public: + ODBCDriverBlockOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings); + + String getName() const override { return "ODBCDriverBlockOutputFormat"; } + + void consume(Chunk) override; + void finalize() override; + + std::string getContentType() const override { return "application/octet-stream"; } + +private: + const FormatSettings format_settings; + bool prefix_written = false; + + void writePrefixIfNot() + { + if (!prefix_written) + writePrefix(); + + prefix_written = true; + } + + void writePrefix(); +}; + +} diff --git a/dbms/src/Processors/Formats/Impl/ParquetBlockInputFormat.cpp b/dbms/src/Processors/Formats/Impl/ParquetBlockInputFormat.cpp new file mode 100644 index 00000000000..9e19f0881ed --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ParquetBlockInputFormat.cpp @@ -0,0 +1,497 @@ +#include "config_formats.h" + +#if USE_PARQUET +#include "ParquetBlockInputFormat.h" + +#include +#include +#include +// TODO: clear includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +//#include +//#include +#include + +#include // REMOVE ME + +namespace DB +{ +namespace ErrorCodes +{ + extern const int UNKNOWN_TYPE; + extern const int VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE; + extern const int CANNOT_READ_ALL_DATA; + extern const int EMPTY_DATA_PASSED; + extern const int SIZES_OF_COLUMNS_DOESNT_MATCH; + extern const int CANNOT_CONVERT_TYPE; + extern const int CANNOT_INSERT_NULL_IN_ORDINARY_COLUMN; + extern const int THERE_IS_NO_COLUMN; +} + +ParquetBlockInputFormat::ParquetBlockInputFormat(ReadBuffer & in_, Block header, const Context & context) + : IInputFormat(std::move(header), in_), context{context} +{ +} + +/// Inserts numeric data right into internal column data to reduce an overhead +template > +static void fillColumnWithNumericData(std::shared_ptr & arrow_column, MutableColumnPtr & internal_column) +{ + auto & column_data = static_cast(*internal_column).getData(); + column_data.reserve(arrow_column->length()); + + for (size_t chunk_i = 0, num_chunks = static_cast(arrow_column->data()->num_chunks()); chunk_i < num_chunks; ++chunk_i) + { + std::shared_ptr chunk = arrow_column->data()->chunk(chunk_i); + /// buffers[0] is a null bitmap and buffers[1] are actual values + std::shared_ptr buffer = chunk->data()->buffers[1]; + + const auto * raw_data = reinterpret_cast(buffer->data()); + column_data.insert_assume_reserved(raw_data, raw_data + chunk->length()); + } +} + +/// Inserts chars and offsets right into internal column data to reduce an overhead. +/// Internal offsets are shifted by one to the right in comparison with Arrow ones. So the last offset should map to the end of all chars. +/// Also internal strings are null terminated. +static void fillColumnWithStringData(std::shared_ptr & arrow_column, MutableColumnPtr & internal_column) +{ + PaddedPODArray & column_chars_t = static_cast(*internal_column).getChars(); + PaddedPODArray & column_offsets = static_cast(*internal_column).getOffsets(); + + size_t chars_t_size = 0; + for (size_t chunk_i = 0, num_chunks = static_cast(arrow_column->data()->num_chunks()); chunk_i < num_chunks; ++chunk_i) + { + arrow::BinaryArray & chunk = static_cast(*(arrow_column->data()->chunk(chunk_i))); + const size_t chunk_length = chunk.length(); + + chars_t_size += chunk.value_offset(chunk_length - 1) + chunk.value_length(chunk_length - 1); + chars_t_size += chunk_length; /// additional space for null bytes + } + + column_chars_t.reserve(chars_t_size); + column_offsets.reserve(arrow_column->length()); + + for (size_t chunk_i = 0, num_chunks = static_cast(arrow_column->data()->num_chunks()); chunk_i < num_chunks; ++chunk_i) + { + arrow::BinaryArray & chunk = static_cast(*(arrow_column->data()->chunk(chunk_i))); + std::shared_ptr buffer = chunk.value_data(); + const size_t chunk_length = chunk.length(); + + for (size_t offset_i = 0; offset_i != chunk_length; ++offset_i) + { + if (!chunk.IsNull(offset_i) && buffer) + { + const UInt8 * raw_data = buffer->data() + chunk.value_offset(offset_i); + column_chars_t.insert_assume_reserved(raw_data, raw_data + chunk.value_length(offset_i)); + } + column_chars_t.emplace_back('\0'); + + column_offsets.emplace_back(column_chars_t.size()); + } + } +} + +static void fillColumnWithBooleanData(std::shared_ptr & arrow_column, MutableColumnPtr & internal_column) +{ + auto & column_data = static_cast &>(*internal_column).getData(); + column_data.resize(arrow_column->length()); + + for (size_t chunk_i = 0, num_chunks = static_cast(arrow_column->data()->num_chunks()); chunk_i < num_chunks; ++chunk_i) + { + arrow::BooleanArray & chunk = static_cast(*(arrow_column->data()->chunk(chunk_i))); + /// buffers[0] is a null bitmap and buffers[1] are actual values + std::shared_ptr buffer = chunk.data()->buffers[1]; + + for (size_t bool_i = 0; bool_i != static_cast(chunk.length()); ++bool_i) + column_data[bool_i] = chunk.Value(bool_i); + } +} + +/// Arrow stores Parquet::DATE in Int32, while ClickHouse stores Date in UInt16. Therefore, it should be checked before saving +static void fillColumnWithDate32Data(std::shared_ptr & arrow_column, MutableColumnPtr & internal_column) +{ + PaddedPODArray & column_data = static_cast &>(*internal_column).getData(); + column_data.reserve(arrow_column->length()); + + for (size_t chunk_i = 0, num_chunks = static_cast(arrow_column->data()->num_chunks()); chunk_i < num_chunks; ++chunk_i) + { + arrow::Date32Array & chunk = static_cast(*(arrow_column->data()->chunk(chunk_i))); + + for (size_t value_i = 0, length = static_cast(chunk.length()); value_i < length; ++value_i) + { + UInt32 days_num = static_cast(chunk.Value(value_i)); + if (days_num > DATE_LUT_MAX_DAY_NUM) + { + // TODO: will it rollback correctly? + throw Exception{"Input value " + std::to_string(days_num) + " of a column \"" + arrow_column->name() + + "\" is greater than " + "max allowed Date value, which is " + + std::to_string(DATE_LUT_MAX_DAY_NUM), + ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE}; + } + + column_data.emplace_back(days_num); + } + } +} + +/// Arrow stores Parquet::DATETIME in Int64, while ClickHouse stores DateTime in UInt32. Therefore, it should be checked before saving +static void fillColumnWithDate64Data(std::shared_ptr & arrow_column, MutableColumnPtr & internal_column) +{ + auto & column_data = static_cast &>(*internal_column).getData(); + column_data.reserve(arrow_column->length()); + + for (size_t chunk_i = 0, num_chunks = static_cast(arrow_column->data()->num_chunks()); chunk_i < num_chunks; ++chunk_i) + { + auto & chunk = static_cast(*(arrow_column->data()->chunk(chunk_i))); + for (size_t value_i = 0, length = static_cast(chunk.length()); value_i < length; ++value_i) + { + auto timestamp = static_cast(chunk.Value(value_i) / 1000); // Always? in ms + column_data.emplace_back(timestamp); + } + } +} + +static void fillColumnWithTimestampData(std::shared_ptr & arrow_column, MutableColumnPtr & internal_column) +{ + auto & column_data = static_cast &>(*internal_column).getData(); + column_data.reserve(arrow_column->length()); + + for (size_t chunk_i = 0, num_chunks = static_cast(arrow_column->data()->num_chunks()); chunk_i < num_chunks; ++chunk_i) + { + auto & chunk = static_cast(*(arrow_column->data()->chunk(chunk_i))); + const auto & type = static_cast(*chunk.type()); + + UInt32 divide = 1; + const auto unit = type.unit(); + switch (unit) + { + case arrow::TimeUnit::SECOND: + divide = 1; + break; + case arrow::TimeUnit::MILLI: + divide = 1000; + break; + case arrow::TimeUnit::MICRO: + divide = 1000000; + break; + case arrow::TimeUnit::NANO: + divide = 1000000000; + break; + } + + for (size_t value_i = 0, length = static_cast(chunk.length()); value_i < length; ++value_i) + { + auto timestamp = static_cast(chunk.Value(value_i) / divide); // ms! TODO: check other 's' 'ns' ... + column_data.emplace_back(timestamp); + } + } +} + +static void fillColumnWithDecimalData(std::shared_ptr & arrow_column, MutableColumnPtr & internal_column) +{ + auto & column = static_cast &>(*internal_column); + auto & column_data = column.getData(); + column_data.reserve(arrow_column->length()); + + for (size_t chunk_i = 0, num_chunks = static_cast(arrow_column->data()->num_chunks()); chunk_i < num_chunks; ++chunk_i) + { + auto & chunk = static_cast(*(arrow_column->data()->chunk(chunk_i))); + for (size_t value_i = 0, length = static_cast(chunk.length()); value_i < length; ++value_i) + { + column_data.emplace_back(chunk.IsNull(value_i) ? Decimal128(0) : *reinterpret_cast(chunk.Value(value_i))); // TODO: copy column + } + } +} + +/// Creates a null bytemap from arrow's null bitmap +static void fillByteMapFromArrowColumn(std::shared_ptr & arrow_column, MutableColumnPtr & bytemap) +{ + PaddedPODArray & bytemap_data = static_cast &>(*bytemap).getData(); + bytemap_data.reserve(arrow_column->length()); + + for (size_t chunk_i = 0; chunk_i != static_cast(arrow_column->data()->num_chunks()); ++chunk_i) + { + std::shared_ptr chunk = arrow_column->data()->chunk(chunk_i); + + for (size_t value_i = 0; value_i != static_cast(chunk->length()); ++value_i) + bytemap_data.emplace_back(chunk->IsNull(value_i)); + } +} + +# define FOR_ARROW_NUMERIC_TYPES(M) \ + M(arrow::Type::UINT8, UInt8) \ + M(arrow::Type::INT8, Int8) \ + M(arrow::Type::UINT16, UInt16) \ + M(arrow::Type::INT16, Int16) \ + M(arrow::Type::UINT32, UInt32) \ + M(arrow::Type::INT32, Int32) \ + M(arrow::Type::UINT64, UInt64) \ + M(arrow::Type::INT64, Int64) \ + M(arrow::Type::FLOAT, Float32) \ + M(arrow::Type::DOUBLE, Float64) +//M(arrow::Type::HALF_FLOAT, Float32) // TODO + + +using NameToColumnPtr = std::unordered_map>; + +const std::unordered_map> arrow_type_to_internal_type = { + //{arrow::Type::DECIMAL, std::make_shared()}, + {arrow::Type::UINT8, std::make_shared()}, + {arrow::Type::INT8, std::make_shared()}, + {arrow::Type::UINT16, std::make_shared()}, + {arrow::Type::INT16, std::make_shared()}, + {arrow::Type::UINT32, std::make_shared()}, + {arrow::Type::INT32, std::make_shared()}, + {arrow::Type::UINT64, std::make_shared()}, + {arrow::Type::INT64, std::make_shared()}, + {arrow::Type::HALF_FLOAT, std::make_shared()}, + {arrow::Type::FLOAT, std::make_shared()}, + {arrow::Type::DOUBLE, std::make_shared()}, + + {arrow::Type::BOOL, std::make_shared()}, + //{arrow::Type::DATE32, std::make_shared()}, + {arrow::Type::DATE32, std::make_shared()}, + //{arrow::Type::DATE32, std::make_shared()}, + {arrow::Type::DATE64, std::make_shared()}, + {arrow::Type::TIMESTAMP, std::make_shared()}, + //{arrow::Type::TIME32, std::make_shared()}, + + + {arrow::Type::STRING, std::make_shared()}, + {arrow::Type::BINARY, std::make_shared()}, + //{arrow::Type::FIXED_SIZE_BINARY, std::make_shared()}, + //{arrow::Type::UUID, std::make_shared()}, + + + // TODO: add other types that are convertable to internal ones: + // 0. ENUM? + // 1. UUID -> String + // 2. JSON -> String + // Full list of types: contrib/arrow/cpp/src/arrow/type.h +}; + + +Chunk ParquetBlockInputFormat::generate() +{ + Chunk res; + Columns columns_list; + UInt64 num_rows = 0; + auto & header = getPort().getHeader(); + columns_list.reserve(header.rows()); + + if (!in.eof()) + { + /* + First we load whole stream into string (its very bad and limiting .parquet file size to half? of RAM) + Then producing blocks for every row_group (dont load big .parquet files with one row_group - it can eat x10+ RAM from .parquet file size) + */ + + if (row_group_current < row_group_total) + throw Exception{"Got new data, but data from previous chunks not readed " + std::to_string(row_group_current) + "/" + std::to_string(row_group_total), ErrorCodes::CANNOT_READ_ALL_DATA}; + + file_data.clear(); + { + WriteBufferFromString file_buffer(file_data); + copyData(in, file_buffer); + } + + buffer = std::make_unique(file_data); + // TODO: maybe use parquet::RandomAccessSource? + auto reader = parquet::ParquetFileReader::Open(std::make_shared<::arrow::io::BufferReader>(*buffer)); + file_reader = std::make_unique(::arrow::default_memory_pool(), std::move(reader)); + row_group_total = file_reader->num_row_groups(); + row_group_current = 0; + } + //DUMP(row_group_current, row_group_total); + if (row_group_current >= row_group_total) + return res; + + // TODO: also catch a ParquetException thrown by filereader? + //arrow::Status read_status = filereader.ReadTable(&table); + std::shared_ptr table; + arrow::Status read_status = file_reader->ReadRowGroup(row_group_current, &table); + + if (!read_status.ok()) + throw Exception{"Error while reading parquet data: " + read_status.ToString(), ErrorCodes::CANNOT_READ_ALL_DATA}; + + if (0 == table->num_rows()) + throw Exception{"Empty table in input data", ErrorCodes::EMPTY_DATA_PASSED}; + + if (header.columns() > static_cast(table->num_columns())) + // TODO: What if some columns were not presented? Insert NULLs? What if a column is not nullable? + throw Exception{"Number of columns is less than the table has", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH}; + + ++row_group_current; + + NameToColumnPtr name_to_column_ptr; + for (size_t i = 0, num_columns = static_cast(table->num_columns()); i < num_columns; ++i) + { + std::shared_ptr arrow_column = table->column(i); + name_to_column_ptr[arrow_column->name()] = arrow_column; + } + + for (size_t column_i = 0, columns = header.columns(); column_i < columns; ++column_i) + { + ColumnWithTypeAndName header_column = header.getByPosition(column_i); + + if (name_to_column_ptr.find(header_column.name) == name_to_column_ptr.end()) + // TODO: What if some columns were not presented? Insert NULLs? What if a column is not nullable? + throw Exception{"Column \"" + header_column.name + "\" is not presented in input data", ErrorCodes::THERE_IS_NO_COLUMN}; + + std::shared_ptr arrow_column = name_to_column_ptr[header_column.name]; + arrow::Type::type arrow_type = arrow_column->type()->id(); + + // TODO: check if a column is const? + if (!header_column.type->isNullable() && arrow_column->null_count()) + { + throw Exception{"Can not insert NULL data into non-nullable column \"" + header_column.name + "\"", + ErrorCodes::CANNOT_INSERT_NULL_IN_ORDINARY_COLUMN}; + } + + const bool target_column_is_nullable = header_column.type->isNullable() || arrow_column->null_count(); + + DataTypePtr internal_nested_type; + + if (arrow_type == arrow::Type::DECIMAL) + { + const auto decimal_type = static_cast(arrow_column->type().get()); + internal_nested_type = std::make_shared>(decimal_type->precision(), decimal_type->scale()); + } + else if (arrow_type_to_internal_type.find(arrow_type) != arrow_type_to_internal_type.end()) + { + internal_nested_type = arrow_type_to_internal_type.at(arrow_type); + } + else + { + throw Exception{"The type \"" + arrow_column->type()->name() + "\" of an input column \"" + arrow_column->name() + + "\" is not supported for conversion from a Parquet data format", + ErrorCodes::CANNOT_CONVERT_TYPE}; + } + + const DataTypePtr internal_type = target_column_is_nullable ? makeNullable(internal_nested_type) : internal_nested_type; + const std::string internal_nested_type_name = internal_nested_type->getName(); + + const DataTypePtr column_nested_type = header_column.type->isNullable() + ? static_cast(header_column.type.get())->getNestedType() + : header_column.type; + + const DataTypePtr column_type = header_column.type; + + const std::string column_nested_type_name = column_nested_type->getName(); + + ColumnWithTypeAndName column; + column.name = header_column.name; + column.type = internal_type; + + /// Data + MutableColumnPtr read_column = internal_nested_type->createColumn(); + switch (arrow_type) + { + case arrow::Type::STRING: + case arrow::Type::BINARY: + //case arrow::Type::FIXED_SIZE_BINARY: + fillColumnWithStringData(arrow_column, read_column); + break; + case arrow::Type::BOOL: + fillColumnWithBooleanData(arrow_column, read_column); + break; + case arrow::Type::DATE32: + fillColumnWithDate32Data(arrow_column, read_column); + break; + case arrow::Type::DATE64: + fillColumnWithDate64Data(arrow_column, read_column); + break; + case arrow::Type::TIMESTAMP: + fillColumnWithTimestampData(arrow_column, read_column); + break; + case arrow::Type::DECIMAL: + //fillColumnWithNumericData>(arrow_column, read_column); // Have problems with trash values under NULL, but faster + fillColumnWithDecimalData(arrow_column, read_column /*, internal_nested_type*/); + break; +# define DISPATCH(ARROW_NUMERIC_TYPE, CPP_NUMERIC_TYPE) \ + case ARROW_NUMERIC_TYPE: \ + fillColumnWithNumericData(arrow_column, read_column); \ + break; + + FOR_ARROW_NUMERIC_TYPES(DISPATCH) +# undef DISPATCH + // TODO: support TIMESTAMP_MICROS and TIMESTAMP_MILLIS with truncated micro- and milliseconds? + // TODO: read JSON as a string? + // TODO: read UUID as a string? + default: + throw Exception{"Unsupported parquet type \"" + arrow_column->type()->name() + "\" of an input column \"" + + arrow_column->name() + "\"", + ErrorCodes::UNKNOWN_TYPE}; + } + + if (column.type->isNullable()) + { + MutableColumnPtr null_bytemap = DataTypeUInt8().createColumn(); + fillByteMapFromArrowColumn(arrow_column, null_bytemap); + column.column = ColumnNullable::create(std::move(read_column), std::move(null_bytemap)); + } + else + { + column.column = std::move(read_column); + } + + column.column = castColumn(column, column_type, context); + column.type = column_type; + num_rows = column.column->size(); + columns_list.push_back(std::move(column.column)); + } + + res.setColumns(columns_list, num_rows); + return res; +} + +void registerInputFormatProcessorParquet(FormatFactory & factory) +{ + factory.registerInputFormatProcessor( + "Parquet", + [](ReadBuffer & buf, + const Block & sample, + const Context & context, + const RowInputFormatParams &, + const FormatSettings & /* settings */){ return std::make_shared(buf, sample, context); }); +} + +} + +#else + +namespace DB +{ +class FormatFactory; +void registerInputFormatProcessorParquet(FormatFactory &) +{ +} +} + +#endif diff --git a/dbms/src/Processors/Formats/Impl/ParquetBlockInputFormat.h b/dbms/src/Processors/Formats/Impl/ParquetBlockInputFormat.h new file mode 100644 index 00000000000..bbb7abdd5d4 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ParquetBlockInputFormat.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#if USE_PARQUET +# include +//# include +//# include +//# include + + +namespace parquet { namespace arrow { class FileReader; } } +namespace arrow { class Buffer; } + +namespace DB +{ +class Context; + +class ParquetBlockInputFormat: public IInputFormat +{ +public: + ParquetBlockInputFormat(ReadBuffer & in_, Block header, const Context & context); + + String getName() const override { return "ParquetBlockInputFormat"; } + +protected: + Chunk generate() override; + +private: + + // TODO: check that this class implements every part of its parent + + const Context & context; + + std::unique_ptr file_reader; + std::string file_data; + std::unique_ptr buffer; + int row_group_total = 0; + int row_group_current = 0; +}; + +} + +#endif diff --git a/dbms/src/Processors/Formats/Impl/ParquetBlockOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/ParquetBlockOutputFormat.cpp new file mode 100644 index 00000000000..26b3dd84f14 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ParquetBlockOutputFormat.cpp @@ -0,0 +1,451 @@ +#include "config_formats.h" + +#if USE_PARQUET +# include "ParquetBlockOutputFormat.h" + +// TODO: clean includes +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include // REMOVE ME + +namespace DB +{ +namespace ErrorCodes +{ + extern const int UNKNOWN_EXCEPTION; + extern const int UNKNOWN_TYPE; +} + +ParquetBlockOutputFormat::ParquetBlockOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings) + : IOutputFormat(header, out_), format_settings{format_settings} +{ +} + +static void checkStatus(arrow::Status & status, const std::string & column_name) +{ + if (!status.ok()) + throw Exception{"Error with a parquet column \"" + column_name + "\": " + status.ToString(), ErrorCodes::UNKNOWN_EXCEPTION}; +} + +template +static void fillArrowArrayWithNumericColumnData( + ColumnPtr write_column, std::shared_ptr & arrow_array, const PaddedPODArray * null_bytemap) +{ + const PaddedPODArray & internal_data = static_cast &>(*write_column).getData(); + ArrowBuilderType builder; + arrow::Status status; + + const UInt8 * arrow_null_bytemap_raw_ptr = nullptr; + PaddedPODArray arrow_null_bytemap; + if (null_bytemap) + { + /// Invert values since Arrow interprets 1 as a non-null value, while CH as a null + arrow_null_bytemap.reserve(null_bytemap->size()); + for (size_t i = 0, size = null_bytemap->size(); i < size; ++i) + arrow_null_bytemap.emplace_back(1 ^ (*null_bytemap)[i]); + + arrow_null_bytemap_raw_ptr = arrow_null_bytemap.data(); + } + + status = builder.AppendValues(internal_data.data(), internal_data.size(), arrow_null_bytemap_raw_ptr); + checkStatus(status, write_column->getName()); + + status = builder.Finish(&arrow_array); + checkStatus(status, write_column->getName()); +} + +template +static void fillArrowArrayWithStringColumnData( + ColumnPtr write_column, std::shared_ptr & arrow_array, const PaddedPODArray * null_bytemap) +{ + const auto & internal_column = static_cast(*write_column); + arrow::StringBuilder builder; + arrow::Status status; + + for (size_t string_i = 0, size = internal_column.size(); string_i < size; ++string_i) + { + if (null_bytemap && (*null_bytemap)[string_i]) + { + status = builder.AppendNull(); + } + else + { + StringRef string_ref = internal_column.getDataAt(string_i); + status = builder.Append(string_ref.data, string_ref.size); + } + + checkStatus(status, write_column->getName()); + } + + status = builder.Finish(&arrow_array); + checkStatus(status, write_column->getName()); +} + +static void fillArrowArrayWithDateColumnData( + ColumnPtr write_column, std::shared_ptr & arrow_array, const PaddedPODArray * null_bytemap) +{ + const PaddedPODArray & internal_data = static_cast &>(*write_column).getData(); + //arrow::Date32Builder date_builder; + arrow::UInt16Builder builder; + arrow::Status status; + + for (size_t value_i = 0, size = internal_data.size(); value_i < size; ++value_i) + { + if (null_bytemap && (*null_bytemap)[value_i]) + status = builder.AppendNull(); + else + /// Implicitly converts UInt16 to Int32 + status = builder.Append(internal_data[value_i]); + checkStatus(status, write_column->getName()); + } + + status = builder.Finish(&arrow_array); + checkStatus(status, write_column->getName()); +} + +static void fillArrowArrayWithDateTimeColumnData( + ColumnPtr write_column, std::shared_ptr & arrow_array, const PaddedPODArray * null_bytemap) +{ + auto & internal_data = static_cast &>(*write_column).getData(); + //arrow::Date64Builder builder; + arrow::UInt32Builder builder; + arrow::Status status; + + for (size_t value_i = 0, size = internal_data.size(); value_i < size; ++value_i) + { + if (null_bytemap && (*null_bytemap)[value_i]) + status = builder.AppendNull(); + else + /// Implicitly converts UInt16 to Int32 + //status = date_builder.Append(static_cast(internal_data[value_i]) * 1000); // now ms. TODO check other units + status = builder.Append(internal_data[value_i]); + + checkStatus(status, write_column->getName()); + } + + status = builder.Finish(&arrow_array); + checkStatus(status, write_column->getName()); +} + +template +static void fillArrowArrayWithDecimalColumnData( + ColumnPtr write_column, + std::shared_ptr & arrow_array, + const PaddedPODArray * null_bytemap, + const DataType * decimal_type) +{ + const auto & column = static_cast(*write_column); + arrow::DecimalBuilder builder(arrow::decimal(decimal_type->getPrecision(), decimal_type->getScale())); + arrow::Status status; + + for (size_t value_i = 0, size = column.size(); value_i < size; ++value_i) + { + if (null_bytemap && (*null_bytemap)[value_i]) + status = builder.AppendNull(); + else + status = builder.Append( + arrow::Decimal128(reinterpret_cast(&column.getElement(value_i).value))); // TODO: try copy column + + checkStatus(status, write_column->getName()); + } + status = builder.Finish(&arrow_array); + checkStatus(status, write_column->getName()); + +/* TODO column copy + const auto & internal_data = static_cast(*write_column).getData(); + //ArrowBuilderType numeric_builder; + arrow::DecimalBuilder builder(arrow::decimal(decimal_type->getPrecision(), decimal_type->getScale())); + arrow::Status status; + + const uint8_t * arrow_null_bytemap_raw_ptr = nullptr; + PaddedPODArray arrow_null_bytemap; + if (null_bytemap) + { + /// Invert values since Arrow interprets 1 as a non-null value, while CH as a null + arrow_null_bytemap.reserve(null_bytemap->size()); + for (size_t i = 0, size = null_bytemap->size(); i < size; ++i) + arrow_null_bytemap.emplace_back(1 ^ (*null_bytemap)[i]); + + arrow_null_bytemap_raw_ptr = arrow_null_bytemap.data(); + } + + status = builder.AppendValues(reinterpret_cast(internal_data.data()), internal_data.size(), arrow_null_bytemap_raw_ptr); + checkStatus(status, write_column->getName()); + + status = builder.Finish(&arrow_array); + checkStatus(status, write_column->getName()); +*/ +} + +# define FOR_INTERNAL_NUMERIC_TYPES(M) \ + M(UInt8, arrow::UInt8Builder) \ + M(Int8, arrow::Int8Builder) \ + M(UInt16, arrow::UInt16Builder) \ + M(Int16, arrow::Int16Builder) \ + M(UInt32, arrow::UInt32Builder) \ + M(Int32, arrow::Int32Builder) \ + M(UInt64, arrow::UInt64Builder) \ + M(Int64, arrow::Int64Builder) \ + M(Float32, arrow::FloatBuilder) \ + M(Float64, arrow::DoubleBuilder) + +const std::unordered_map> internal_type_to_arrow_type = { + {"UInt8", arrow::uint8()}, + {"Int8", arrow::int8()}, + {"UInt16", arrow::uint16()}, + {"Int16", arrow::int16()}, + {"UInt32", arrow::uint32()}, + {"Int32", arrow::int32()}, + {"UInt64", arrow::uint64()}, + {"Int64", arrow::int64()}, + {"Float32", arrow::float32()}, + {"Float64", arrow::float64()}, + + //{"Date", arrow::date64()}, + //{"Date", arrow::date32()}, + {"Date", arrow::uint16()}, // CHECK + //{"DateTime", arrow::date64()}, // BUG! saves as date32 + {"DateTime", arrow::uint32()}, + + // TODO: ClickHouse can actually store non-utf8 strings! + {"String", arrow::utf8()}, + {"FixedString", arrow::utf8()}, +}; + +static const PaddedPODArray * extractNullBytemapPtr(ColumnPtr column) +{ + ColumnPtr null_column = static_cast(*column).getNullMapColumnPtr(); + const PaddedPODArray & null_bytemap = static_cast &>(*null_column).getData(); + return &null_bytemap; +} + + +class OstreamOutputStream : public parquet::OutputStream +{ +public: + explicit OstreamOutputStream(WriteBuffer & ostr_) : ostr(ostr_) {} + virtual ~OstreamOutputStream() {} + virtual void Close() {} + virtual int64_t Tell() { return total_length; } + virtual void Write(const uint8_t * data, int64_t length) + { + ostr.write(reinterpret_cast(data), length); + total_length += length; + } + +private: + WriteBuffer & ostr; + int64_t total_length = 0; + + PARQUET_DISALLOW_COPY_AND_ASSIGN(OstreamOutputStream); +}; + + +void ParquetBlockOutputFormat::consume(Chunk chunk) +{ + auto & header = getPort(PortKind::Main).getHeader(); + const size_t columns_num = chunk.getNumColumns(); + + /// For arrow::Schema and arrow::Table creation + std::vector> arrow_fields; + std::vector> arrow_arrays; + arrow_fields.reserve(columns_num); + arrow_arrays.reserve(columns_num); + + for (size_t column_i = 0; column_i < columns_num; ++column_i) + { + // TODO: constructed every iteration + ColumnWithTypeAndName column = header.safeGetByPosition(column_i); + column.column = chunk.getColumns()[column_i]; + + const bool is_column_nullable = column.type->isNullable(); + const auto & column_nested_type + = is_column_nullable ? static_cast(column.type.get())->getNestedType() : column.type; + const std::string column_nested_type_name = column_nested_type->getFamilyName(); + + if (isDecimal(column_nested_type)) + { + const auto add_decimal_field = [&](const auto & types) -> bool { + using Types = std::decay_t; + using ToDataType = typename Types::LeftType; + + if constexpr ( + std::is_same_v< + ToDataType, + DataTypeDecimal< + Decimal32>> || std::is_same_v> || std::is_same_v>) + { + const auto & decimal_type = static_cast(column_nested_type.get()); + arrow_fields.emplace_back(std::make_shared( + column.name, arrow::decimal(decimal_type->getPrecision(), decimal_type->getScale()), is_column_nullable)); + } + + return false; + }; + callOnIndexAndDataType(column_nested_type->getTypeId(), add_decimal_field); + } + else + { + if (internal_type_to_arrow_type.find(column_nested_type_name) == internal_type_to_arrow_type.end()) + { + throw Exception{"The type \"" + column_nested_type_name + "\" of a column \"" + column.name + + "\"" + " is not supported for conversion into a Parquet data format", + ErrorCodes::UNKNOWN_TYPE}; + } + + arrow_fields.emplace_back(std::make_shared(column.name, internal_type_to_arrow_type.at(column_nested_type_name), is_column_nullable)); + } + + std::shared_ptr arrow_array; + + ColumnPtr nested_column + = is_column_nullable ? static_cast(*column.column).getNestedColumnPtr() : column.column; + const PaddedPODArray * null_bytemap = is_column_nullable ? extractNullBytemapPtr(column.column) : nullptr; + + if ("String" == column_nested_type_name) + { + fillArrowArrayWithStringColumnData(nested_column, arrow_array, null_bytemap); + } + else if ("FixedString" == column_nested_type_name) + { + fillArrowArrayWithStringColumnData(nested_column, arrow_array, null_bytemap); + } + else if ("Date" == column_nested_type_name) + { + fillArrowArrayWithDateColumnData(nested_column, arrow_array, null_bytemap); + } + else if ("DateTime" == column_nested_type_name) + { + fillArrowArrayWithDateTimeColumnData(nested_column, arrow_array, null_bytemap); + } + + else if (isDecimal(column_nested_type)) + { + auto fill_decimal = [&](const auto & types) -> bool + { + using Types = std::decay_t; + using ToDataType = typename Types::LeftType; + if constexpr ( + std::is_same_v< + ToDataType, + DataTypeDecimal< + Decimal32>> || std::is_same_v> || std::is_same_v>) + { + const auto & decimal_type = static_cast(column_nested_type.get()); + fillArrowArrayWithDecimalColumnData(nested_column, arrow_array, null_bytemap, decimal_type); + } + return false; + }; + callOnIndexAndDataType(column_nested_type->getTypeId(), fill_decimal); + } +# define DISPATCH(CPP_NUMERIC_TYPE, ARROW_BUILDER_TYPE) \ + else if (#CPP_NUMERIC_TYPE == column_nested_type_name) \ + { \ + fillArrowArrayWithNumericColumnData(nested_column, arrow_array, null_bytemap); \ + } + + FOR_INTERNAL_NUMERIC_TYPES(DISPATCH) +# undef DISPATCH + else + { + throw Exception{"Internal type \"" + column_nested_type_name + "\" of a column \"" + column.name + + "\"" + " is not supported for conversion into a Parquet data format", + ErrorCodes::UNKNOWN_TYPE}; + } + + + arrow_arrays.emplace_back(std::move(arrow_array)); + } + + std::shared_ptr arrow_schema = std::make_shared(std::move(arrow_fields)); + + std::shared_ptr arrow_table = arrow::Table::Make(arrow_schema, arrow_arrays); + + auto sink = std::make_shared(out); + + if (!file_writer) + { + + parquet::WriterProperties::Builder builder; +#if USE_SNAPPY + builder.compression(parquet::Compression::SNAPPY); +#endif + auto props = builder.build(); + auto status = parquet::arrow::FileWriter::Open( + *arrow_table->schema(), + arrow::default_memory_pool(), + sink, + props, /*parquet::default_writer_properties(),*/ + parquet::arrow::default_arrow_writer_properties(), + &file_writer); + if (!status.ok()) + throw Exception{"Error while opening a table: " + status.ToString(), ErrorCodes::UNKNOWN_EXCEPTION}; + } + + // TODO: calculate row_group_size depending on a number of rows and table size + auto status = file_writer->WriteTable(*arrow_table, format_settings.parquet.row_group_size); + + if (!status.ok()) + throw Exception{"Error while writing a table: " + status.ToString(), ErrorCodes::UNKNOWN_EXCEPTION}; +} + +void ParquetBlockOutputFormat::finalize() +{ + if (file_writer) + { + auto status = file_writer->Close(); + if (!status.ok()) + throw Exception{"Error while closing a table: " + status.ToString(), ErrorCodes::UNKNOWN_EXCEPTION}; + } +} + + +void registerOutputFormatProcessorParquet(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor( + "Parquet", [](WriteBuffer & buf, const Block & sample, const Context & /*context*/, const FormatSettings & format_settings) + { + auto impl = std::make_shared(buf, sample, format_settings); + /// TODO + // auto res = std::make_shared(impl, impl->getHeader(), format_settings.parquet.row_group_size, 0); + // res->disableFlush(); + return impl; + }); +} + +} + + +#else + +namespace DB +{ +class FormatFactory; +void registerOutputFormatProcessorParquet(FormatFactory &) +{ +} +} + + +#endif diff --git a/dbms/src/Processors/Formats/Impl/ParquetBlockOutputFormat.h b/dbms/src/Processors/Formats/Impl/ParquetBlockOutputFormat.h new file mode 100644 index 00000000000..de2deba50b3 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ParquetBlockOutputFormat.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#if USE_PARQUET +# include +# include + +namespace arrow +{ +class Array; +class DataType; +} + +namespace parquet +{ +namespace arrow +{ + class FileWriter; +} +} + +namespace DB +{ +class ParquetBlockOutputFormat : public IOutputFormat +{ +public: + ParquetBlockOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings); + + String getName() const override { return "ParquetBlockOutputFormat"; } + void consume(Chunk) override; + void finalize() override; + + String getContentType() const override { return "application/octet-stream"; } + +private: + const FormatSettings format_settings; + + std::unique_ptr file_writer; +}; + +} + +#endif diff --git a/dbms/src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp new file mode 100644 index 00000000000..6868a3b2987 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/PrettyBlockOutputFormat.cpp @@ -0,0 +1,281 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int ILLEGAL_COLUMN; +} + + +PrettyBlockOutputFormat::PrettyBlockOutputFormat( + WriteBuffer & out_, const Block & header, const FormatSettings & format_settings_) + : IOutputFormat(header, out_), format_settings(format_settings_) +{ + struct winsize w; + if (0 == ioctl(STDOUT_FILENO, TIOCGWINSZ, &w)) + terminal_width = w.ws_col; +} + + +/// Evaluate the visible width of the values and column names. +/// Note that number of code points is just a rough approximation of visible string width. +void PrettyBlockOutputFormat::calculateWidths( + const Block & header, const Chunk & chunk, + WidthsPerColumn & widths, Widths & max_widths, Widths & name_widths) +{ + size_t num_rows = chunk.getNumRows(); + size_t num_columns = chunk.getNumColumns(); + auto & columns = chunk.getColumns(); + + widths.resize(num_columns); + max_widths.resize_fill(num_columns); + name_widths.resize(num_columns); + + /// Calculate widths of all values. + String serialized_value; + size_t prefix = 2; // Tab character adjustment + for (size_t i = 0; i < num_columns; ++i) + { + auto & elem = header.getByPosition(i); + auto & column = columns[i]; + + widths[i].resize(num_rows); + + for (size_t j = 0; j < num_rows; ++j) + { + { + WriteBufferFromString out(serialized_value); + elem.type->serializeAsText(*column, j, out, format_settings); + } + + widths[i][j] = std::min(format_settings.pretty.max_column_pad_width, + UTF8::computeWidth(reinterpret_cast(serialized_value.data()), serialized_value.size(), prefix)); + max_widths[i] = std::max(max_widths[i], widths[i][j]); + } + + /// And also calculate widths for names of columns. + { + // name string doesn't contain Tab, no need to pass `prefix` + name_widths[i] = std::min(format_settings.pretty.max_column_pad_width, + UTF8::computeWidth(reinterpret_cast(elem.name.data()), elem.name.size())); + max_widths[i] = std::max(max_widths[i], name_widths[i]); + } + prefix += max_widths[i] + 3; + } +} + + +void PrettyBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind) +{ + UInt64 max_rows = format_settings.pretty.max_rows; + + if (total_rows >= max_rows) + { + total_rows += chunk.getNumRows(); + return; + } + + auto num_rows = chunk.getNumRows(); + auto num_columns = chunk.getNumColumns(); + auto & columns = chunk.getColumns(); + auto & header = getPort(port_kind).getHeader(); + + WidthsPerColumn widths; + Widths max_widths; + Widths name_widths; + calculateWidths(header, chunk, widths, max_widths, name_widths); + + /// Create separators + std::stringstream top_separator; + std::stringstream middle_names_separator; + std::stringstream middle_values_separator; + std::stringstream bottom_separator; + + top_separator << "┏"; + middle_names_separator << "┡"; + middle_values_separator << "├"; + bottom_separator << "└"; + for (size_t i = 0; i < num_columns; ++i) + { + if (i != 0) + { + top_separator << "┳"; + middle_names_separator << "╇"; + middle_values_separator << "┼"; + bottom_separator << "┴"; + } + + for (size_t j = 0; j < max_widths[i] + 2; ++j) + { + top_separator << "━"; + middle_names_separator << "━"; + middle_values_separator << "─"; + bottom_separator << "─"; + } + } + top_separator << "┓\n"; + middle_names_separator << "┩\n"; + middle_values_separator << "┤\n"; + bottom_separator << "┘\n"; + + std::string top_separator_s = top_separator.str(); + std::string middle_names_separator_s = middle_names_separator.str(); + std::string middle_values_separator_s = middle_values_separator.str(); + std::string bottom_separator_s = bottom_separator.str(); + + /// Output the block + writeString(top_separator_s, out); + + /// Names + writeCString("┃ ", out); + for (size_t i = 0; i < num_columns; ++i) + { + if (i != 0) + writeCString(" ┃ ", out); + + auto & col = header.getByPosition(i); + + if (format_settings.pretty.color) + writeCString("\033[1m", out); + + if (col.type->shouldAlignRightInPrettyFormats()) + { + for (size_t k = 0; k < max_widths[i] - name_widths[i]; ++k) + writeChar(' ', out); + + writeString(col.name, out); + } + else + { + writeString(col.name, out); + + for (size_t k = 0; k < max_widths[i] - name_widths[i]; ++k) + writeChar(' ', out); + } + + if (format_settings.pretty.color) + writeCString("\033[0m", out); + } + writeCString(" ┃\n", out); + + writeString(middle_names_separator_s, out); + + for (size_t i = 0; i < num_rows && total_rows + i < max_rows; ++i) + { + if (i != 0) + writeString(middle_values_separator_s, out); + + writeCString("│ ", out); + + for (size_t j = 0; j < num_columns; ++j) + { + if (j != 0) + writeCString(" │ ", out); + + auto & type = *header.getByPosition(j).type; + writeValueWithPadding(*columns[j], type, i, widths[j].empty() ? max_widths[j] : widths[j][i], max_widths[j]); + } + + writeCString(" │\n", out); + } + + writeString(bottom_separator_s, out); + + total_rows += num_rows; +} + + +void PrettyBlockOutputFormat::writeValueWithPadding( + const IColumn & column, const IDataType & type, size_t row_num, size_t value_width, size_t pad_to_width) +{ + auto writePadding = [&]() + { + for (size_t k = 0; k < pad_to_width - value_width; ++k) + writeChar(' ', out); + }; + + if (type.shouldAlignRightInPrettyFormats()) + { + writePadding(); + type.serializeAsText(column, row_num, out, format_settings); + } + else + { + type.serializeAsText(column, row_num, out, format_settings); + writePadding(); + } +} + + +void PrettyBlockOutputFormat::consume(Chunk chunk) +{ + write(chunk, PortKind::Main); +} + +void PrettyBlockOutputFormat::consumeTotals(Chunk chunk) +{ + total_rows = 0; + writeSuffixIfNot(); + writeCString("\nExtremes:\n", out); + write(chunk, PortKind::Totals); +} + +void PrettyBlockOutputFormat::consumeExtremes(Chunk chunk) +{ + total_rows = 0; + writeSuffixIfNot(); + writeCString("\nTotals:\n", out); + write(chunk, PortKind::Extremes); +} + + +void PrettyBlockOutputFormat::writeSuffix() +{ + if (total_rows >= format_settings.pretty.max_rows) + { + writeCString(" Showed first ", out); + writeIntText(format_settings.pretty.max_rows, out); + writeCString(".\n", out); + } +} + +void PrettyBlockOutputFormat::finalize() +{ + writeSuffixIfNot(); +} + + +void registerOutputFormatProcessorPretty(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("Pretty", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & format_settings) + { + return std::make_shared(buf, sample, format_settings); + }); + + factory.registerOutputFormatProcessor("PrettyNoEscapes", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & format_settings) + { + FormatSettings changed_settings = format_settings; + changed_settings.pretty.color = false; + return std::make_shared(buf, sample, changed_settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/PrettyBlockOutputFormat.h b/dbms/src/Processors/Formats/Impl/PrettyBlockOutputFormat.h new file mode 100644 index 00000000000..34bbbc3000c --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/PrettyBlockOutputFormat.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include + + +namespace DB +{ + +class WriteBuffer; +class Context; + + +/** Prints the result in the form of beautiful tables. + */ +class PrettyBlockOutputFormat : public IOutputFormat +{ +public: + /// no_escapes - do not use ANSI escape sequences - to display in the browser, not in the console. + PrettyBlockOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings_); + + String getName() const override { return "PrettyBlockOutputFormat"; } + + void consume(Chunk) override; + void consumeTotals(Chunk) override; + void consumeExtremes(Chunk) override; + + void finalize() override; + +protected: + size_t total_rows = 0; + size_t terminal_width = 0; + bool suffix_written = false; + + const FormatSettings format_settings; + + using Widths = PODArray; + using WidthsPerColumn = std::vector; + + virtual void write(const Chunk & chunk, PortKind port_kind); + virtual void writeSuffix(); + + + void writeSuffixIfNot() + { + if (!suffix_written) + writeSuffix(); + + suffix_written = true; + } + + void calculateWidths( + const Block & header, const Chunk & chunk, + WidthsPerColumn & widths, Widths & max_widths, Widths & name_widths); + + void writeValueWithPadding( + const IColumn & column, const IDataType & type, size_t row_num, size_t value_width, size_t pad_to_width); +}; + +} diff --git a/dbms/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.cpp new file mode 100644 index 00000000000..53fef75a97c --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.cpp @@ -0,0 +1,167 @@ +#include +#include +///#include +#include +#include + + +namespace DB +{ + +namespace ErrorCodes +{ + +extern const int ILLEGAL_COLUMN; + +} + +void PrettyCompactBlockOutputFormat::writeHeader( + const Block & block, + const Widths & max_widths, + const Widths & name_widths) +{ + /// Names + writeCString("┌─", out); + for (size_t i = 0; i < max_widths.size(); ++i) + { + if (i != 0) + writeCString("─┬─", out); + + const ColumnWithTypeAndName & col = block.getByPosition(i); + + if (col.type->shouldAlignRightInPrettyFormats()) + { + for (size_t k = 0; k < max_widths[i] - name_widths[i]; ++k) + writeCString("─", out); + + if (format_settings.pretty.color) + writeCString("\033[1m", out); + writeString(col.name, out); + if (format_settings.pretty.color) + writeCString("\033[0m", out); + } + else + { + if (format_settings.pretty.color) + writeCString("\033[1m", out); + writeString(col.name, out); + if (format_settings.pretty.color) + writeCString("\033[0m", out); + + for (size_t k = 0; k < max_widths[i] - name_widths[i]; ++k) + writeCString("─", out); + } + } + writeCString("─┐\n", out); +} + +void PrettyCompactBlockOutputFormat::writeBottom(const Widths & max_widths) +{ + /// Create delimiters + std::stringstream bottom_separator; + + bottom_separator << "└"; + for (size_t i = 0; i < max_widths.size(); ++i) + { + if (i != 0) + bottom_separator << "┴"; + + for (size_t j = 0; j < max_widths[i] + 2; ++j) + bottom_separator << "─"; + } + bottom_separator << "┘\n"; + + writeString(bottom_separator.str(), out); +} + +void PrettyCompactBlockOutputFormat::writeRow( + size_t row_num, + const Block & header, + const Columns & columns, + const WidthsPerColumn & widths, + const Widths & max_widths) +{ + size_t num_columns = max_widths.size(); + + writeCString("│ ", out); + + for (size_t j = 0; j < num_columns; ++j) + { + if (j != 0) + writeCString(" │ ", out); + + auto & type = *header.getByPosition(j).type; + auto & cur_widths = widths[j].empty() ? max_widths[j] : widths[j][row_num]; + writeValueWithPadding(*columns[j], type, row_num, cur_widths, max_widths[j]); + } + + writeCString(" │\n", out); +} + +void PrettyCompactBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind) +{ + UInt64 max_rows = format_settings.pretty.max_rows; + + if (total_rows >= max_rows) + { + total_rows += chunk.getNumRows(); + return; + } + + size_t num_rows = chunk.getNumRows(); + auto & header = getPort(port_kind).getHeader(); + auto & columns = chunk.getColumns(); + + WidthsPerColumn widths; + Widths max_widths; + Widths name_widths; + calculateWidths(header, chunk, widths, max_widths, name_widths); + + writeHeader(header, max_widths, name_widths); + + for (size_t i = 0; i < num_rows && total_rows + i < max_rows; ++i) + writeRow(i, header, columns, widths, max_widths); + + writeBottom(max_widths); + + total_rows += num_rows; +} + + +void registerOutputFormatProcessorPrettyCompact(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("PrettyCompact", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & format_settings) + { + return std::make_shared(buf, sample, format_settings); + }); + + factory.registerOutputFormatProcessor("PrettyCompactNoEscapes", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & format_settings) + { + FormatSettings changed_settings = format_settings; + changed_settings.pretty.color = false; + return std::make_shared(buf, sample, changed_settings); + }); + +/// TODO +// factory.registerOutputFormat("PrettyCompactMonoBlock", []( +// WriteBuffer & buf, +// const Block & sample, +// const Context &, +// const FormatSettings & format_settings) +// { +// BlockOutputStreamPtr impl = std::make_shared(buf, sample, format_settings); +// auto res = std::make_shared(impl, impl->getHeader(), format_settings.pretty.max_rows, 0); +// res->disableFlush(); +// return res; +// }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.h b/dbms/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.h new file mode 100644 index 00000000000..8130577995a --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/PrettyCompactBlockOutputFormat.h @@ -0,0 +1,31 @@ +#pragma once + +#include + + +namespace DB +{ + +/** Prints the result in the form of beautiful tables, but with fewer delimiter lines. + */ +class PrettyCompactBlockOutputFormat : public PrettyBlockOutputFormat +{ +public: + PrettyCompactBlockOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings_) + : PrettyBlockOutputFormat(out_, header, format_settings_) {} + + String getName() const override { return "PrettyCompactBlockOutputFormat"; } + +protected: + void write(const Chunk & chunk, PortKind port_kind) override; + void writeHeader(const Block & block, const Widths & max_widths, const Widths & name_widths); + void writeBottom(const Widths & max_widths); + void writeRow( + size_t row_num, + const Block & header, + const Columns & columns, + const WidthsPerColumn & widths, + const Widths & max_widths); +}; + +} diff --git a/dbms/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.cpp new file mode 100644 index 00000000000..2b75d867327 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.cpp @@ -0,0 +1,123 @@ +#include +#include +#include +#include + + +namespace DB +{ + + +void PrettySpaceBlockOutputFormat::write(const Chunk & chunk, PortKind port_kind) +{ + UInt64 max_rows = format_settings.pretty.max_rows; + + if (total_rows >= max_rows) + { + total_rows += chunk.getNumRows(); + return; + } + + size_t num_rows = chunk.getNumRows(); + size_t num_columns = chunk.getNumColumns(); + auto & header = getPort(port_kind).getHeader(); + auto & columns = chunk.getColumns(); + + WidthsPerColumn widths; + Widths max_widths; + Widths name_widths; + calculateWidths(header, chunk, widths, max_widths, name_widths); + + /// Do not align on too long values. + if (terminal_width > 80) + for (size_t i = 0; i < num_columns; ++i) + if (max_widths[i] > terminal_width / 2) + max_widths[i] = terminal_width / 2; + + /// Names + for (size_t i = 0; i < num_columns; ++i) + { + if (i != 0) + writeCString(" ", out); + + const ColumnWithTypeAndName & col = header.getByPosition(i); + + if (col.type->shouldAlignRightInPrettyFormats()) + { + for (ssize_t k = 0; k < std::max(static_cast(0), static_cast(max_widths[i] - name_widths[i])); ++k) + writeChar(' ', out); + + if (format_settings.pretty.color) + writeCString("\033[1m", out); + writeString(col.name, out); + if (format_settings.pretty.color) + writeCString("\033[0m", out); + } + else + { + if (format_settings.pretty.color) + writeCString("\033[1m", out); + writeString(col.name, out); + if (format_settings.pretty.color) + writeCString("\033[0m", out); + + for (ssize_t k = 0; k < std::max(static_cast(0), static_cast(max_widths[i] - name_widths[i])); ++k) + writeChar(' ', out); + } + } + writeCString("\n\n", out); + + for (size_t row = 0; row < num_rows && total_rows + row < max_rows; ++row) + { + for (size_t column = 0; column < num_columns; ++column) + { + if (column != 0) + writeCString(" ", out); + + auto & type = *header.getByPosition(column).type; + auto & cur_width = widths[column].empty() ? max_widths[column] : widths[column][row]; + writeValueWithPadding(*columns[column], type, row, cur_width, max_widths[column]); + } + + writeChar('\n', out); + } + + total_rows += num_rows; +} + + +void PrettySpaceBlockOutputFormat::writeSuffix() +{ + if (total_rows >= format_settings.pretty.max_rows) + { + writeCString("\nShowed first ", out); + writeIntText(format_settings.pretty.max_rows, out); + writeCString(".\n", out); + } +} + + +void registerOutputFormatProcessorPrettySpace(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("PrettySpace", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & format_settings) + { + return std::make_shared(buf, sample, format_settings); + }); + + factory.registerOutputFormatProcessor("PrettySpaceNoEscapes", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & format_settings) + { + FormatSettings changed_settings = format_settings; + changed_settings.pretty.color = false; + return std::make_shared(buf, sample, changed_settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.h b/dbms/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.h new file mode 100644 index 00000000000..a041d324fd3 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/PrettySpaceBlockOutputFormat.h @@ -0,0 +1,24 @@ +#pragma once + +#include + + +namespace DB +{ + +/** Prints the result, aligned with spaces. + */ +class PrettySpaceBlockOutputFormat : public PrettyBlockOutputFormat +{ +public: + PrettySpaceBlockOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings_) + : PrettyBlockOutputFormat(out_, header, format_settings_) {} + + String getName() const override { return "PrettySpaceBlockOutputFormat"; } + +protected: + void write(const Chunk & chunk, PortKind port_kind) override; + void writeSuffix() override; +}; + +} diff --git a/dbms/src/Processors/Formats/Impl/ProtobufBlockOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/ProtobufBlockOutputFormat.cpp new file mode 100644 index 00000000000..03c8ef1b2ac --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ProtobufBlockOutputFormat.cpp @@ -0,0 +1,73 @@ +#include + +#include "config_formats.h" +#if USE_PROTOBUF + +#include + +#include +#include +#include +#include +#include + + + +namespace DB +{ +namespace ErrorCodes +{ + extern const int NOT_IMPLEMENTED; + extern const int NO_DATA_FOR_REQUIRED_PROTOBUF_FIELD; +} + + +ProtobufBlockOutputFormat::ProtobufBlockOutputFormat( + WriteBuffer & out_, + const Block & header, + const FormatSchemaInfo & format_schema) + : IOutputFormat(header, out_) + , data_types(header.getDataTypes()) + , writer(out, ProtobufSchemas::instance().getMessageTypeForFormatSchema(format_schema), header.getNames()) +{ + value_indices.resize(header.columns()); +} + +void ProtobufBlockOutputFormat::consume(Chunk chunk) +{ + auto & columns = chunk.getColumns(); + auto num_rows = chunk.getNumRows(); + + for (UInt64 row_num = 0; row_num < num_rows; ++row_num) + { + writer.startMessage(); + std::fill(value_indices.begin(), value_indices.end(), 0); + size_t column_index; + while (writer.writeField(column_index)) + data_types[column_index]->serializeProtobuf( + *columns[column_index], row_num, writer, value_indices[column_index]); + writer.endMessage(); + } +} + + +void registerOutputFormatProcessorProtobuf(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor( + "Protobuf", [](WriteBuffer & buf, const Block & header, const Context & context, const FormatSettings &) + { + return std::make_shared(buf, header, FormatSchemaInfo(context, "Protobuf")); + }); +} + +} + +#else + +namespace DB +{ + class FormatFactory; + void registerOutputFormatProcessorProtobuf(FormatFactory &) {} +} + +#endif diff --git a/dbms/src/Processors/Formats/Impl/ProtobufBlockOutputFormat.h b/dbms/src/Processors/Formats/Impl/ProtobufBlockOutputFormat.h new file mode 100644 index 00000000000..9cc5c7af68e --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ProtobufBlockOutputFormat.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#if USE_PROTOBUF + +#include +#include +#include +#include +#include + + +namespace google +{ +namespace protobuf +{ + class Message; +} +} + + +namespace DB +{ +/** Stream designed to serialize data in the google protobuf format. + * Each row is written as a separated message. + * These messages are delimited according to documentation + * https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/util/delimited_message_util.h + * Serializing in the protobuf format requires the 'format_schema' setting to be set, e.g. + * SELECT * from table FORMAT Protobuf SETTINGS format_schema = 'schema:Message' + * where schema is the name of "schema.proto" file specifying protobuf schema. + */ +class ProtobufBlockOutputFormat : public IOutputFormat +{ +public: + ProtobufBlockOutputFormat( + WriteBuffer & out_, + const Block & header, + const FormatSchemaInfo & format_schema); + + String getName() const override { return "ProtobufBlockOutputFormat"; } + + void consume(Chunk) override; + + std::string getContentType() const override { return "application/octet-stream"; } + +private: + DataTypes data_types; + ProtobufWriter writer; + std::vector value_indices; +}; + +} +#endif diff --git a/dbms/src/Processors/Formats/Impl/ProtobufRowInputFormat.cpp b/dbms/src/Processors/Formats/Impl/ProtobufRowInputFormat.cpp new file mode 100644 index 00000000000..a2f3a47def3 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ProtobufRowInputFormat.cpp @@ -0,0 +1,92 @@ +#include "config_formats.h" +#if USE_PROTOBUF + +#include +#include +#include +#include +#include + + +namespace DB +{ + +ProtobufRowInputFormat::ProtobufRowInputFormat(ReadBuffer & in_, const Block & header, Params params, const FormatSchemaInfo & info) + : IRowInputFormat(header, in_, params) + , data_types(header.getDataTypes()) + , reader(in, ProtobufSchemas::instance().getMessageTypeForFormatSchema(info), header.getNames()) +{ +} + +ProtobufRowInputFormat::~ProtobufRowInputFormat() = default; + +bool ProtobufRowInputFormat::readRow(MutableColumns & columns, RowReadExtension & extra) +{ + if (!reader.startMessage()) + return false; // EOF reached, no more messages. + + // Set of columns for which the values were read. The rest will be filled with default values. + auto & read_columns = extra.read_columns; + read_columns.assign(columns.size(), false); + + // Read values from this message and put them to the columns while it's possible. + size_t column_index; + while (reader.readColumnIndex(column_index)) + { + bool allow_add_row = !static_cast(read_columns[column_index]); + do + { + bool row_added; + data_types[column_index]->deserializeProtobuf(*columns[column_index], reader, allow_add_row, row_added); + if (row_added) + { + read_columns[column_index] = true; + allow_add_row = false; + } + } while (reader.maybeCanReadValue()); + } + + // Fill non-visited columns with the default values. + for (column_index = 0; column_index < read_columns.size(); ++column_index) + if (!read_columns[column_index]) + data_types[column_index]->insertDefaultInto(*columns[column_index]); + + reader.endMessage(); + return true; +} + +bool ProtobufRowInputFormat::allowSyncAfterError() const +{ + return true; +} + +void ProtobufRowInputFormat::syncAfterError() +{ + reader.endMessage(); +} + + +void registerInputFormatProcessorProtobuf(FormatFactory & factory) +{ + factory.registerInputFormatProcessor("Protobuf", []( + ReadBuffer & buf, + const Block & sample, + const Context & context, + IRowInputFormat::Params params, + const FormatSettings &) + { + return std::make_shared(buf, sample, params, FormatSchemaInfo(context, "proto")); + }); +} + +} + +#else + +namespace DB +{ +class FormatFactory; +void registerInputFormatProcessorProtobuf(FormatFactory &) {} +} + +#endif diff --git a/dbms/src/Processors/Formats/Impl/ProtobufRowInputFormat.h b/dbms/src/Processors/Formats/Impl/ProtobufRowInputFormat.h new file mode 100644 index 00000000000..77c6350d371 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ProtobufRowInputFormat.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#if USE_PROTOBUF + +#include +#include +#include + +namespace DB +{ +class Block; +class FormatSchemaInfo; + + +/** Interface of stream, that allows to read data by rows. + */ +class ProtobufRowInputFormat : public IRowInputFormat +{ +public: + ProtobufRowInputFormat(ReadBuffer & in_, const Block & header, Params params, const FormatSchemaInfo & info); + ~ProtobufRowInputFormat() override; + + String getName() const override { return "ProtobufRowInputFormat"; } + + bool readRow(MutableColumns & columns, RowReadExtension & extra) override; + bool allowSyncAfterError() const override; + void syncAfterError() override; + +private: + DataTypes data_types; + ProtobufReader reader; +}; + +} +#endif diff --git a/dbms/src/Processors/Formats/Impl/TSKVRowInputFormat.cpp b/dbms/src/Processors/Formats/Impl/TSKVRowInputFormat.cpp new file mode 100644 index 00000000000..7750962beec --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/TSKVRowInputFormat.cpp @@ -0,0 +1,207 @@ +#include +#include +#include + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int INCORRECT_DATA; + extern const int CANNOT_PARSE_ESCAPE_SEQUENCE; + extern const int CANNOT_READ_ALL_DATA; + extern const int CANNOT_PARSE_INPUT_ASSERTION_FAILED; +} + + +TSKVRowInputFormat::TSKVRowInputFormat(ReadBuffer & in_, Block header, Params params, const FormatSettings & format_settings) + : IRowInputFormat(std::move(header), in_, params), format_settings(format_settings), name_map(header.columns()) +{ + /// In this format, we assume that column name cannot contain BOM, + /// so BOM at beginning of stream cannot be confused with name of field, and it is safe to skip it. + skipBOMIfExists(in); + + size_t num_columns = header.columns(); + for (size_t i = 0; i < num_columns; ++i) + name_map[header.safeGetByPosition(i).name] = i; /// NOTE You could place names more cache-locally. +} + + +/** Read the field name in the `tskv` format. + * Return true if the field is followed by an equal sign, + * otherwise (field with no value) return false. + * The reference to the field name will be written to `ref`. + * A temporary `tmp` buffer can also be used to copy the field name to it. + * When reading, skips the name and the equal sign after it. + */ +static bool readName(ReadBuffer & buf, StringRef & ref, String & tmp) +{ + tmp.clear(); + + while (!buf.eof()) + { + const char * next_pos = find_first_symbols<'\t', '\n', '\\', '='>(buf.position(), buf.buffer().end()); + + if (next_pos == buf.buffer().end()) + { + tmp.append(buf.position(), next_pos - buf.position()); + buf.next(); + continue; + } + + /// Came to the end of the name. + if (*next_pos != '\\') + { + bool have_value = *next_pos == '='; + if (tmp.empty()) + { + /// No need to copy data, you can refer directly to the `buf`. + ref = StringRef(buf.position(), next_pos - buf.position()); + buf.position() += next_pos + have_value - buf.position(); + } + else + { + /// Copy the data to a temporary string and return a reference to it. + tmp.append(buf.position(), next_pos - buf.position()); + buf.position() += next_pos + have_value - buf.position(); + ref = StringRef(tmp); + } + return have_value; + } + /// The name has an escape sequence. + else + { + tmp.append(buf.position(), next_pos - buf.position()); + buf.position() += next_pos + 1 - buf.position(); + if (buf.eof()) + throw Exception("Cannot parse escape sequence", ErrorCodes::CANNOT_PARSE_ESCAPE_SEQUENCE); + + tmp.push_back(parseEscapeSequence(*buf.position())); + ++buf.position(); + continue; + } + } + + throw Exception("Unexpected end of stream while reading key name from TSKV format", ErrorCodes::CANNOT_READ_ALL_DATA); +} + + +bool TSKVRowInputFormat::readRow(MutableColumns & columns, RowReadExtension & ext) +{ + if (in.eof()) + return false; + + auto & header = getPort().getHeader(); + size_t num_columns = columns.size(); + + /// Set of columns for which the values were read. The rest will be filled with default values. + read_columns.assign(num_columns, false); + + if (unlikely(*in.position() == '\n')) + { + /// An empty string. It is permissible, but it is unclear why. + ++in.position(); + } + else + { + while (true) + { + StringRef name_ref; + bool has_value = readName(in, name_ref, name_buf); + ssize_t index = -1; + + if (has_value) + { + /// NOTE Optimization is possible by caching the order of fields (which is almost always the same) + /// and quickly checking for the next expected field, instead of searching the hash table. + + auto it = name_map.find(name_ref); + if (name_map.end() == it) + { + if (!format_settings.skip_unknown_fields) + throw Exception("Unknown field found while parsing TSKV format: " + name_ref.toString(), ErrorCodes::INCORRECT_DATA); + + /// If the key is not found, skip the value. + NullSink sink; + readEscapedStringInto(sink, in); + } + else + { + index = it->getSecond(); + + if (read_columns[index]) + throw Exception("Duplicate field found while parsing TSKV format: " + name_ref.toString(), ErrorCodes::INCORRECT_DATA); + + read_columns[index] = true; + + header.getByPosition(index).type->deserializeAsTextEscaped(*columns[index], in, format_settings); + } + } + else + { + /// The only thing that can go without value is `tskv` fragment that is ignored. + if (!(name_ref.size == 4 && 0 == memcmp(name_ref.data, "tskv", 4))) + throw Exception("Found field without value while parsing TSKV format: " + name_ref.toString(), ErrorCodes::INCORRECT_DATA); + } + + if (in.eof()) + { + throw Exception("Unexpected end of stream after field in TSKV format: " + name_ref.toString(), ErrorCodes::CANNOT_READ_ALL_DATA); + } + else if (*in.position() == '\t') + { + ++in.position(); + continue; + } + else if (*in.position() == '\n') + { + ++in.position(); + break; + } + else + { + /// Possibly a garbage was written into column, remove it + if (index >= 0) + { + columns[index]->popBack(1); + read_columns[index] = false; + } + + throw Exception("Found garbage after field in TSKV format: " + name_ref.toString(), ErrorCodes::CANNOT_PARSE_INPUT_ASSERTION_FAILED); + } + } + } + + /// Fill in the not met columns with default values. + for (size_t i = 0; i < num_columns; ++i) + if (!read_columns[i]) + header.getByPosition(i).type->insertDefaultInto(*columns[i]); + + /// return info about defaults set + ext.read_columns = read_columns; + + return true; +} + + +void TSKVRowInputFormat::syncAfterError() +{ + skipToUnescapedNextLineOrEOF(in); +} + + +void registerInputFormatProcessorTSKV(FormatFactory & factory) +{ + factory.registerInputFormatProcessor("TSKV", []( + ReadBuffer & buf, + const Block & sample, + const Context &, + IRowInputFormat::Params params, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, params, settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/TSKVRowInputFormat.h b/dbms/src/Processors/Formats/Impl/TSKVRowInputFormat.h new file mode 100644 index 00000000000..4d9c55f6efc --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/TSKVRowInputFormat.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include + + +namespace DB +{ + +class ReadBuffer; + + +/** Stream for reading data in TSKV format. + * TSKV is a very inefficient data format. + * Similar to TSV, but each field is written as key=value. + * Fields can be listed in any order (including, in different lines there may be different order), + * and some fields may be missing. + * An equal sign can be escaped in the field name. + * Also, as an additional element there may be a useless tskv fragment - it needs to be ignored. + */ +class TSKVRowInputFormat : public IRowInputFormat +{ +public: + TSKVRowInputFormat(ReadBuffer & in_, Block header, Params params, const FormatSettings & format_settings); + + String getName() const override { return "TSKVRowInputFormat"; } + + bool readRow(MutableColumns & columns, RowReadExtension &) override; + bool allowSyncAfterError() const override { return true; } + void syncAfterError() override; + +private: + const FormatSettings format_settings; + + /// Buffer for the read from the stream the field name. Used when you have to copy it. + String name_buf; + + /// Hash table matching `field name -> position in the block`. NOTE You can use perfect hash map. + using NameMap = HashMap; + NameMap name_map; + + std::vector read_columns; +}; + +} diff --git a/dbms/src/Processors/Formats/Impl/TSKVRowOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/TSKVRowOutputFormat.cpp new file mode 100644 index 00000000000..f1c13af9c5d --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/TSKVRowOutputFormat.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include + + + +namespace DB +{ + +TSKVRowOutputFormat::TSKVRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings_) + : TabSeparatedRowOutputFormat(out_, header, false, false, format_settings_) +{ + auto & sample = getPort(PortKind::Main).getHeader(); + NamesAndTypesList columns(sample.getNamesAndTypesList()); + fields.assign(columns.begin(), columns.end()); + + for (auto & field : fields) + { + WriteBufferFromOwnString wb; + writeAnyEscapedString<'='>(field.name.data(), field.name.data() + field.name.size(), wb); + writeCString("=", wb); + field.name = wb.str(); + } +} + + +void TSKVRowOutputFormat::writeField(const IColumn & column, const IDataType & type, size_t row_num) +{ + writeString(fields[field_number].name, out); + type.serializeAsTextEscaped(column, row_num, out, format_settings); + ++field_number; +} + + +void TSKVRowOutputFormat::writeRowEndDelimiter() +{ + writeChar('\n', out); + field_number = 0; +} + + +void registerOutputFormatProcessorTSKV(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("TSKV", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/TSKVRowOutputFormat.h b/dbms/src/Processors/Formats/Impl/TSKVRowOutputFormat.h new file mode 100644 index 00000000000..607fa5fdc9b --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/TSKVRowOutputFormat.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + + +namespace DB +{ + +/** The stream for outputting data in the TSKV format. + * TSKV is similar to TabSeparated, but before every value, its name and equal sign are specified: name=value. + * This format is very inefficient. + */ +class TSKVRowOutputFormat: public TabSeparatedRowOutputFormat +{ +public: + TSKVRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings); + + String getName() const override { return "TSKVRowOutputFormat"; } + + void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; + void writeRowEndDelimiter() override; + +protected: + NamesAndTypes fields; + size_t field_number = 0; +}; + +} + diff --git a/dbms/src/Processors/Formats/Impl/TabSeparatedRawRowOutputFormat.h b/dbms/src/Processors/Formats/Impl/TabSeparatedRawRowOutputFormat.h new file mode 100644 index 00000000000..2d2d7cf4ad4 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/TabSeparatedRawRowOutputFormat.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + + +namespace DB +{ + +/** A stream for outputting data in tsv format, but without escaping individual values. + * (That is, the output is irreversible.) + */ +class TabSeparatedRawRowOutputFormat : public TabSeparatedRowOutputFormat +{ +public: + TabSeparatedRawRowOutputFormat(WriteBuffer & out_, const Block & header, bool with_names_, bool with_types_, const FormatSettings & format_settings_) + : TabSeparatedRowOutputFormat(out_, header, with_names_, with_types_, format_settings_) {} + + String getName() const override { return "TabSeparatedRawRowOutputFormat"; } + + void writeField(const IColumn & column, const IDataType & type, size_t row_num) override + { + type.serializeAsText(column, row_num, out, format_settings); + } +}; + +} + diff --git a/dbms/src/Processors/Formats/Impl/TabSeparatedRowInputFormat.cpp b/dbms/src/Processors/Formats/Impl/TabSeparatedRowInputFormat.cpp new file mode 100644 index 00000000000..ab7562a0036 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/TabSeparatedRowInputFormat.cpp @@ -0,0 +1,370 @@ +#include +#include +#include + +#include +#include +#include + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int INCORRECT_DATA; + extern const int LOGICAL_ERROR; +} + + +TabSeparatedRowInputFormat::TabSeparatedRowInputFormat( + ReadBuffer & in_, Block header, bool with_names, bool with_types, Params params, const FormatSettings & format_settings) + : IRowInputFormat(std::move(header), in_, params), with_names(with_names), with_types(with_types), format_settings(format_settings) +{ + auto & sample = getPort().getHeader(); + size_t num_columns = sample.columns(); + data_types.resize(num_columns); + for (size_t i = 0; i < num_columns; ++i) + data_types[i] = sample.safeGetByPosition(i).type; +} + + +void TabSeparatedRowInputFormat::readPrefix() +{ + auto & header = getPort().getHeader(); + size_t num_columns = header.columns(); + String tmp; + + if (with_names || with_types) + { + /// In this format, we assume that column name or type cannot contain BOM, + /// so, if format has header, + /// then BOM at beginning of stream cannot be confused with name or type of field, and it is safe to skip it. + skipBOMIfExists(in); + } + + if (with_names) + { + for (size_t i = 0; i < num_columns; ++i) + { + readEscapedString(tmp, in); + assertChar(i == num_columns - 1 ? '\n' : '\t', in); + } + } + + if (with_types) + { + for (size_t i = 0; i < num_columns; ++i) + { + readEscapedString(tmp, in); + assertChar(i == num_columns - 1 ? '\n' : '\t', in); + } + } +} + + +/** Check for a common error case - usage of Windows line feed. + */ +static void checkForCarriageReturn(ReadBuffer & in) +{ + if (in.position()[0] == '\r' || (in.position() != in.buffer().begin() && in.position()[-1] == '\r')) + throw Exception("\nYou have carriage return (\\r, 0x0D, ASCII 13) at end of first row." + "\nIt's like your input data has DOS/Windows style line separators, that are illegal in TabSeparated format." + " You must transform your file to Unix format." + "\nBut if you really need carriage return at end of string value of last column, you need to escape it as \\r.", + ErrorCodes::INCORRECT_DATA); +} + + +bool TabSeparatedRowInputFormat::readRow(MutableColumns & columns, RowReadExtension &) +{ + if (in.eof()) + return false; + + updateDiagnosticInfo(); + + size_t size = data_types.size(); + + for (size_t i = 0; i < size; ++i) + { + data_types[i]->deserializeAsTextEscaped(*columns[i], in, format_settings); + + /// skip separators + if (i + 1 == size) + { + if (!in.eof()) + { + if (unlikely(row_num == 1)) + checkForCarriageReturn(in); + + assertChar('\n', in); + } + } + else + assertChar('\t', in); + } + + return true; +} + + +String TabSeparatedRowInputFormat::getDiagnosticInfo() +{ + if (in.eof()) /// Buffer has gone, cannot extract information about what has been parsed. + return {}; + + auto & header = getPort().getHeader(); + WriteBufferFromOwnString out; + MutableColumns columns = header.cloneEmptyColumns(); + + /// It is possible to display detailed diagnostics only if the last and next to last lines are still in the read buffer. + size_t bytes_read_at_start_of_buffer = in.count() - in.offset(); + if (bytes_read_at_start_of_buffer != bytes_read_at_start_of_buffer_on_prev_row) + { + out << "Could not print diagnostic info because two last rows aren't in buffer (rare case)\n"; + return out.str(); + } + + size_t max_length_of_column_name = 0; + for (size_t i = 0; i < header.columns(); ++i) + if (header.safeGetByPosition(i).name.size() > max_length_of_column_name) + max_length_of_column_name = header.safeGetByPosition(i).name.size(); + + size_t max_length_of_data_type_name = 0; + for (size_t i = 0; i < header.columns(); ++i) + if (header.safeGetByPosition(i).type->getName().size() > max_length_of_data_type_name) + max_length_of_data_type_name = header.safeGetByPosition(i).type->getName().size(); + + /// Roll back the cursor to the beginning of the previous or current line and pars all over again. But now we derive detailed information. + + if (pos_of_prev_row) + { + in.position() = pos_of_prev_row; + + out << "\nRow " << (row_num - 1) << ":\n"; + if (!parseRowAndPrintDiagnosticInfo(columns, out, max_length_of_column_name, max_length_of_data_type_name)) + return out.str(); + } + else + { + if (!pos_of_current_row) + { + out << "Could not print diagnostic info because parsing of data hasn't started.\n"; + return out.str(); + } + + in.position() = pos_of_current_row; + } + + out << "\nRow " << row_num << ":\n"; + parseRowAndPrintDiagnosticInfo(columns, out, max_length_of_column_name, max_length_of_data_type_name); + out << "\n"; + + return out.str(); +} + + +bool TabSeparatedRowInputFormat::parseRowAndPrintDiagnosticInfo(MutableColumns & columns, + WriteBuffer & out, size_t max_length_of_column_name, size_t max_length_of_data_type_name) +{ + auto & header = getPort().getHeader(); + size_t size = data_types.size(); + for (size_t i = 0; i < size; ++i) + { + if (i == 0 && in.eof()) + { + out << "\n"; + return false; + } + + out << "Column " << i << ", " << std::string((i < 10 ? 2 : i < 100 ? 1 : 0), ' ') + << "name: " << header.safeGetByPosition(i).name << ", " << std::string(max_length_of_column_name - header.safeGetByPosition(i).name.size(), ' ') + << "type: " << data_types[i]->getName() << ", " << std::string(max_length_of_data_type_name - data_types[i]->getName().size(), ' '); + + auto prev_position = in.position(); + std::exception_ptr exception; + + try + { + data_types[i]->deserializeAsTextEscaped(*columns[i], in, format_settings); + } + catch (...) + { + exception = std::current_exception(); + } + + auto curr_position = in.position(); + + if (curr_position < prev_position) + throw Exception("Logical error: parsing is non-deterministic.", ErrorCodes::LOGICAL_ERROR); + + if (isNumber(data_types[i]) || isDateOrDateTime(data_types[i])) + { + /// An empty string instead of a value. + if (curr_position == prev_position) + { + out << "ERROR: text "; + verbosePrintString(prev_position, std::min(prev_position + 10, in.buffer().end()), out); + out << " is not like " << data_types[i]->getName() << "\n"; + return false; + } + } + + out << "parsed text: "; + verbosePrintString(prev_position, curr_position, out); + + if (exception) + { + if (data_types[i]->getName() == "DateTime") + out << "ERROR: DateTime must be in YYYY-MM-DD hh:mm:ss or NNNNNNNNNN (unix timestamp, exactly 10 digits) format.\n"; + else if (data_types[i]->getName() == "Date") + out << "ERROR: Date must be in YYYY-MM-DD format.\n"; + else + out << "ERROR\n"; + return false; + } + + out << "\n"; + + if (data_types[i]->haveMaximumSizeOfValue()) + { + if (*curr_position != '\n' && *curr_position != '\t') + { + out << "ERROR: garbage after " << data_types[i]->getName() << ": "; + verbosePrintString(curr_position, std::min(curr_position + 10, in.buffer().end()), out); + out << "\n"; + + if (data_types[i]->getName() == "DateTime") + out << "ERROR: DateTime must be in YYYY-MM-DD hh:mm:ss or NNNNNNNNNN (unix timestamp, exactly 10 digits) format.\n"; + else if (data_types[i]->getName() == "Date") + out << "ERROR: Date must be in YYYY-MM-DD format.\n"; + + return false; + } + } + + /// Delimiters + if (i + 1 == size) + { + if (!in.eof()) + { + try + { + assertChar('\n', in); + } + catch (const DB::Exception &) + { + if (*in.position() == '\t') + { + out << "ERROR: Tab found where line feed is expected." + " It's like your file has more columns than expected.\n" + "And if your file have right number of columns, maybe it have unescaped tab in value.\n"; + } + else if (*in.position() == '\r') + { + out << "ERROR: Carriage return found where line feed is expected." + " It's like your file has DOS/Windows style line separators, that is illegal in TabSeparated format.\n"; + } + else + { + out << "ERROR: There is no line feed. "; + verbosePrintString(in.position(), in.position() + 1, out); + out << " found instead.\n"; + } + return false; + } + } + } + else + { + try + { + assertChar('\t', in); + } + catch (const DB::Exception &) + { + if (*in.position() == '\n') + { + out << "ERROR: Line feed found where tab is expected." + " It's like your file has less columns than expected.\n" + "And if your file have right number of columns, maybe it have unescaped backslash in value before tab, which cause tab has escaped.\n"; + } + else if (*in.position() == '\r') + { + out << "ERROR: Carriage return found where tab is expected.\n"; + } + else + { + out << "ERROR: There is no tab. "; + verbosePrintString(in.position(), in.position() + 1, out); + out << " found instead.\n"; + } + return false; + } + } + } + + return true; +} + + +void TabSeparatedRowInputFormat::syncAfterError() +{ + skipToUnescapedNextLineOrEOF(in); +} + + +void TabSeparatedRowInputFormat::updateDiagnosticInfo() +{ + ++row_num; + + bytes_read_at_start_of_buffer_on_prev_row = bytes_read_at_start_of_buffer_on_current_row; + bytes_read_at_start_of_buffer_on_current_row = in.count() - in.offset(); + + pos_of_prev_row = pos_of_current_row; + pos_of_current_row = in.position(); +} + + +void registerInputFormatProcessorTabSeparated(FormatFactory & factory) +{ + for (auto name : {"TabSeparated", "TSV"}) + { + factory.registerInputFormatProcessor(name, []( + ReadBuffer & buf, + const Block & sample, + const Context &, + IRowInputFormat::Params params, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, false, false, params, settings); + }); + } + + for (auto name : {"TabSeparatedWithNames", "TSVWithNames"}) + { + factory.registerInputFormatProcessor(name, []( + ReadBuffer & buf, + const Block & sample, + const Context &, + IRowInputFormat::Params params, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, true, false, params, settings); + }); + } + + for (auto name : {"TabSeparatedWithNamesAndTypes", "TSVWithNamesAndTypes"}) + { + factory.registerInputFormatProcessor(name, []( + ReadBuffer & buf, + const Block & sample, + const Context &, + IRowInputFormat::Params params, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, true, true, params, settings); + }); + } +} + +} diff --git a/dbms/src/Processors/Formats/Impl/TabSeparatedRowInputFormat.h b/dbms/src/Processors/Formats/Impl/TabSeparatedRowInputFormat.h new file mode 100644 index 00000000000..b91884d9db5 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/TabSeparatedRowInputFormat.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include + + +namespace DB +{ + +class ReadBuffer; + + +/** A stream to input data in tsv format. + */ +class TabSeparatedRowInputFormat : public IRowInputFormat +{ +public: + /** with_names - the first line is the header with the names of the columns + * with_types - on the next line header with type names + */ + TabSeparatedRowInputFormat( + ReadBuffer & in_, Block header, bool with_names, bool with_types, Params params, const FormatSettings & format_settings); + + String getName() const override { return "TabSeparatedRowInputFormat"; } + + bool readRow(MutableColumns & columns, RowReadExtension &) override; + void readPrefix() override; + bool allowSyncAfterError() const override { return true; } + void syncAfterError() override; + + std::string getDiagnosticInfo() override; + +private: + bool with_names; + bool with_types; + const FormatSettings format_settings; + DataTypes data_types; + + /// For convenient diagnostics in case of an error. + + size_t row_num = 0; + + /// How many bytes were read, not counting those still in the buffer. + size_t bytes_read_at_start_of_buffer_on_current_row = 0; + size_t bytes_read_at_start_of_buffer_on_prev_row = 0; + + char * pos_of_current_row = nullptr; + char * pos_of_prev_row = nullptr; + + void updateDiagnosticInfo(); + + bool parseRowAndPrintDiagnosticInfo(MutableColumns & columns, + WriteBuffer & out, size_t max_length_of_column_name, size_t max_length_of_data_type_name); +}; + +} diff --git a/dbms/src/Processors/Formats/Impl/TabSeparatedRowOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/TabSeparatedRowOutputFormat.cpp new file mode 100644 index 00000000000..608f2e8b5d0 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/TabSeparatedRowOutputFormat.cpp @@ -0,0 +1,121 @@ +#include +#include +#include +#include + + +namespace DB +{ + +TabSeparatedRowOutputFormat::TabSeparatedRowOutputFormat( + WriteBuffer & out_, const Block & header, bool with_names, bool with_types, const FormatSettings & format_settings) + : IRowOutputFormat(header, out_), with_names(with_names), with_types(with_types), format_settings(format_settings) +{ +} + + +void TabSeparatedRowOutputFormat::writePrefix() +{ + auto & header = getPort(PortKind::Main).getHeader(); + size_t columns = header.columns(); + + if (with_names) + { + for (size_t i = 0; i < columns; ++i) + { + writeEscapedString(header.safeGetByPosition(i).name, out); + writeChar(i == columns - 1 ? '\n' : '\t', out); + } + } + + if (with_types) + { + for (size_t i = 0; i < columns; ++i) + { + writeEscapedString(header.safeGetByPosition(i).type->getName(), out); + writeChar(i == columns - 1 ? '\n' : '\t', out); + } + } +} + + +void TabSeparatedRowOutputFormat::writeField(const IColumn & column, const IDataType & type, size_t row_num) +{ + type.serializeAsTextEscaped(column, row_num, out, format_settings); +} + + +void TabSeparatedRowOutputFormat::writeFieldDelimiter() +{ + writeChar('\t', out); +} + + +void TabSeparatedRowOutputFormat::writeRowEndDelimiter() +{ + writeChar('\n', out); +} + +void TabSeparatedRowOutputFormat::writeBeforeTotals() +{ + writeChar('\n', out); +} + +void TabSeparatedRowOutputFormat::writeBeforeExtremes() +{ + writeChar('\n', out); +} + + +void registerOutputFormatProcessorTabSeparated(FormatFactory & factory) +{ + for (auto name : {"TabSeparated", "TSV"}) + { + factory.registerOutputFormatProcessor(name, []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, false, false, settings); + }); + } + + for (auto name : {"TabSeparatedRaw", "TSVRaw"}) + { + factory.registerOutputFormatProcessor(name, []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, false, false, settings); + }); + } + + for (auto name : {"TabSeparatedWithNames", "TSVWithNames"}) + { + factory.registerOutputFormatProcessor(name, []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, true, false, settings); + }); + } + + for (auto name : {"TabSeparatedWithNamesAndTypes", "TSVWithNamesAndTypes"}) + { + factory.registerOutputFormatProcessor(name, []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, true, true, settings); + }); + } +} + +} diff --git a/dbms/src/Processors/Formats/Impl/TabSeparatedRowOutputFormat.h b/dbms/src/Processors/Formats/Impl/TabSeparatedRowOutputFormat.h new file mode 100644 index 00000000000..7ebe12bc30d --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/TabSeparatedRowOutputFormat.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include + + +namespace DB +{ + +class WriteBuffer; + +/** A stream for outputting data in tsv format. + */ +class TabSeparatedRowOutputFormat : public IRowOutputFormat +{ +public: + /** with_names - output in the first line a header with column names + * with_types - output the next line header with the names of the types + */ + TabSeparatedRowOutputFormat(WriteBuffer & out_, const Block & header, bool with_names, bool with_types, const FormatSettings & format_settings); + + String getName() const override { return "TabSeparatedRowOutputFormat"; } + + void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; + void writeFieldDelimiter() override; + void writeRowEndDelimiter() override; + void writePrefix() override; + void writeBeforeTotals() override; + void writeBeforeExtremes() override; + + /// https://www.iana.org/assignments/media-types/text/tab-separated-values + String getContentType() const override { return "text/tab-separated-values; charset=UTF-8"; } + +protected: + + bool with_names; + bool with_types; + const FormatSettings format_settings; +}; + +} + diff --git a/dbms/src/Processors/Formats/Impl/ValuesRowInputFormat.cpp b/dbms/src/Processors/Formats/Impl/ValuesRowInputFormat.cpp new file mode 100644 index 00000000000..7b0287596ad --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ValuesRowInputFormat.cpp @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int CANNOT_PARSE_INPUT_ASSERTION_FAILED; + extern const int CANNOT_PARSE_QUOTED_STRING; + extern const int CANNOT_PARSE_NUMBER; + extern const int CANNOT_PARSE_DATE; + extern const int CANNOT_PARSE_DATETIME; + extern const int CANNOT_READ_ARRAY_FROM_TEXT; + extern const int CANNOT_PARSE_DATE; + extern const int SYNTAX_ERROR; + extern const int VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE; +} + + +ValuesRowInputFormat::ValuesRowInputFormat( + ReadBuffer & in_, Block header, Params params, const Context & context_, const FormatSettings & format_settings) + : IRowInputFormat(std::move(header), in_, params) + , context(std::make_unique(context_)), format_settings(format_settings) +{ + /// In this format, BOM at beginning of stream cannot be confused with value, so it is safe to skip it. + skipBOMIfExists(in); +} + + +bool ValuesRowInputFormat::readRow(MutableColumns & columns, RowReadExtension &) +{ + size_t num_columns = columns.size(); + auto & header = getPort().getHeader(); + + skipWhitespaceIfAny(in); + + if (in.eof() || *in.position() == ';') + return false; + + /** Typically, this is the usual format for streaming parsing. + * But as an exception, it also supports processing arbitrary expressions instead of values. + * This is very inefficient. But if there are no expressions, then there is no overhead. + */ + ParserExpression parser; + + assertChar('(', in); + + for (size_t i = 0; i < num_columns; ++i) + { + skipWhitespaceIfAny(in); + + char * prev_in_position = in.position(); + size_t prev_in_bytes = in.count() - in.offset(); + + bool rollback_on_exception = false; + try + { + header.getByPosition(i).type->deserializeAsTextQuoted(*columns[i], in, format_settings); + rollback_on_exception = true; + skipWhitespaceIfAny(in); + + if (i != num_columns - 1) + assertChar(',', in); + else + assertChar(')', in); + } + catch (const Exception & e) + { + if (!format_settings.values.interpret_expressions) + throw; + + /** The normal streaming parser could not parse the value. + * Let's try to parse it with a SQL parser as a constant expression. + * This is an exceptional case. + */ + if (e.code() == ErrorCodes::CANNOT_PARSE_INPUT_ASSERTION_FAILED + || e.code() == ErrorCodes::CANNOT_PARSE_QUOTED_STRING + || e.code() == ErrorCodes::CANNOT_PARSE_NUMBER + || e.code() == ErrorCodes::CANNOT_PARSE_DATE + || e.code() == ErrorCodes::CANNOT_PARSE_DATETIME + || e.code() == ErrorCodes::CANNOT_READ_ARRAY_FROM_TEXT) + { + /// TODO Case when the expression does not fit entirely in the buffer. + + /// If the beginning of the value is no longer in the buffer. + if (in.count() - in.offset() != prev_in_bytes) + throw; + + if (rollback_on_exception) + columns[i]->popBack(1); + + const IDataType & type = *header.getByPosition(i).type; + + Expected expected; + + Tokens tokens(prev_in_position, in.buffer().end()); + TokenIterator token_iterator(tokens); + + ASTPtr ast; + if (!parser.parse(token_iterator, ast, expected)) + throw Exception("Cannot parse expression of type " + type.getName() + " here: " + + String(prev_in_position, std::min(SHOW_CHARS_ON_SYNTAX_ERROR, in.buffer().end() - prev_in_position)), + ErrorCodes::SYNTAX_ERROR); + + in.position() = const_cast(token_iterator->begin); + + std::pair value_raw = evaluateConstantExpression(ast, *context); + Field value = convertFieldToType(value_raw.first, type, value_raw.second.get()); + + /// Check that we are indeed allowed to insert a NULL. + if (value.isNull()) + { + if (!type.isNullable()) + throw Exception{"Expression returns value " + applyVisitor(FieldVisitorToString(), value) + + ", that is out of range of type " + type.getName() + + ", at: " + String(prev_in_position, std::min(SHOW_CHARS_ON_SYNTAX_ERROR, in.buffer().end() - prev_in_position)), + ErrorCodes::VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE}; + } + + columns[i]->insert(value); + + skipWhitespaceIfAny(in); + + if (i != num_columns - 1) + assertChar(',', in); + else + assertChar(')', in); + } + else + throw; + } + } + + skipWhitespaceIfAny(in); + if (!in.eof() && *in.position() == ',') + ++in.position(); + + return true; +} + + +void registerInputFormatProcessorValues(FormatFactory & factory) +{ + factory.registerInputFormatProcessor("Values", []( + ReadBuffer & buf, + const Block & sample, + const Context & context, + IRowInputFormat::Params params, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, params, context, settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/ValuesRowInputFormat.h b/dbms/src/Processors/Formats/Impl/ValuesRowInputFormat.h new file mode 100644 index 00000000000..f7ad3b470e6 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ValuesRowInputFormat.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include + + +namespace DB +{ + +class Context; +class ReadBuffer; + + +/** Stream to read data in VALUES format (as in INSERT query). + */ +class ValuesRowInputFormat : public IRowInputFormat +{ +public: + /** Data is parsed using fast, streaming parser. + * If interpret_expressions is true, it will, in addition, try to use SQL parser and interpreter + * in case when streaming parser could not parse field (this is very slow). + */ + ValuesRowInputFormat(ReadBuffer & in_, Block header, Params params, const Context & context_, const FormatSettings & format_settings); + + String getName() const override { return "ValuesRowInputFormat"; } + + bool readRow(MutableColumns & columns, RowReadExtension &) override; + +private: + std::unique_ptr context; /// pimpl + const FormatSettings format_settings; +}; + +} diff --git a/dbms/src/Processors/Formats/Impl/ValuesRowOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/ValuesRowOutputFormat.cpp new file mode 100644 index 00000000000..234a9da5c67 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ValuesRowOutputFormat.cpp @@ -0,0 +1,56 @@ +#include +#include + +#include +#include +#include + + +namespace DB +{ + + +ValuesRowOutputFormat::ValuesRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings) + : IRowOutputFormat(header, out_), format_settings(format_settings) +{ +} + +void ValuesRowOutputFormat::writeField(const IColumn & column, const IDataType & type, size_t row_num) +{ + type.serializeAsTextQuoted(column, row_num, out, format_settings); +} + +void ValuesRowOutputFormat::writeFieldDelimiter() +{ + writeChar(',', out); +} + +void ValuesRowOutputFormat::writeRowStartDelimiter() +{ + writeChar('(', out); +} + +void ValuesRowOutputFormat::writeRowEndDelimiter() +{ + writeChar(')', out); +} + +void ValuesRowOutputFormat::writeRowBetweenDelimiter() +{ + writeCString(",", out); +} + + +void registerOutputFormatProcessorValues(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("Values", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/ValuesRowOutputFormat.h b/dbms/src/Processors/Formats/Impl/ValuesRowOutputFormat.h new file mode 100644 index 00000000000..5f82e78d3c0 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/ValuesRowOutputFormat.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + + +namespace DB +{ + +class WriteBuffer; + + +/** A stream for outputting data in the VALUES format (as in the INSERT request). + */ +class ValuesRowOutputFormat : public IRowOutputFormat +{ +public: + ValuesRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings); + + String getName() const override { return "ValuesRowOutputFormat"; } + + void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; + void writeFieldDelimiter() override; + void writeRowStartDelimiter() override; + void writeRowEndDelimiter() override; + void writeRowBetweenDelimiter() override; + +private: + const FormatSettings format_settings; +}; + +} + diff --git a/dbms/src/Processors/Formats/Impl/VerticalRowOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/VerticalRowOutputFormat.cpp new file mode 100644 index 00000000000..8e9d0cd37c5 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/VerticalRowOutputFormat.cpp @@ -0,0 +1,177 @@ +#include + +#include +#include +#include +#include +#include + + +namespace DB +{ + +VerticalRowOutputFormat::VerticalRowOutputFormat( + WriteBuffer & out_, const Block & header, const FormatSettings & format_settings) + : IRowOutputFormat(header, out_), format_settings(format_settings) +{ + auto & sample = getPort(PortKind::Main).getHeader(); + size_t columns = sample.columns(); + + using Widths = std::vector; + Widths name_widths(columns); + size_t max_name_width = 0; + + String serialized_value; + + for (size_t i = 0; i < columns; ++i) + { + /// Note that number of code points is just a rough approximation of visible string width. + const String & name = sample.getByPosition(i).name; + + name_widths[i] = UTF8::computeWidth(reinterpret_cast(name.data()), name.size()); + + if (name_widths[i] > max_name_width) + max_name_width = name_widths[i]; + } + + names_and_paddings.resize(columns); + for (size_t i = 0; i < columns; ++i) + { + WriteBufferFromString buf(names_and_paddings[i]); + writeString(sample.getByPosition(i).name, buf); + writeCString(": ", buf); + } + + for (size_t i = 0; i < columns; ++i) + { + size_t new_size = max_name_width - name_widths[i] + names_and_paddings[i].size(); + names_and_paddings[i].resize(new_size, ' '); + } +} + + +void VerticalRowOutputFormat::writeField(const IColumn & column, const IDataType & type, size_t row_num) +{ + if (row_number > format_settings.pretty.max_rows) + return; + + writeString(names_and_paddings[field_number], out); + writeValue(column, type, row_num); + writeChar('\n', out); + + ++field_number; +} + + +void VerticalRowOutputFormat::writeValue(const IColumn & column, const IDataType & type, size_t row_num) const +{ + type.serializeAsText(column, row_num, out, format_settings); +} + + +void VerticalRowOutputFormat::writeRowStartDelimiter() +{ + ++row_number; + + if (row_number > format_settings.pretty.max_rows) + return; + + writeCString("Row ", out); + writeIntText(row_number, out); + writeCString(":\n", out); + + size_t width = log10(row_number + 1) + 1 + strlen("Row :"); + for (size_t i = 0; i < width; ++i) + writeCString("─", out); + writeChar('\n', out); +} + + +void VerticalRowOutputFormat::writeRowBetweenDelimiter() +{ + if (row_number > format_settings.pretty.max_rows) + return; + + writeCString("\n", out); + field_number = 0; +} + + +void VerticalRowOutputFormat::writeSuffix() +{ + if (row_number > format_settings.pretty.max_rows) + { + writeCString("Showed first ", out); + writeIntText(format_settings.pretty.max_rows, out); + writeCString(".\n", out); + } +} + +void VerticalRowOutputFormat::writeBeforeTotals() +{ + writeCString("\n", out); +} + +void VerticalRowOutputFormat::writeBeforeExtremes() +{ + if (!was_totals_written) + writeCString("\n", out); +} + +void VerticalRowOutputFormat::writeMinExtreme(const Columns & columns, size_t row_num) +{ + writeSpecialRow(columns, row_num, PortKind::Totals, "Min"); +} + +void VerticalRowOutputFormat::writeMaxExtreme(const Columns & columns, size_t row_num) +{ + writeSpecialRow(columns, row_num, PortKind::Totals, "Max"); +} + +void VerticalRowOutputFormat::writeTotals(const Columns & columns, size_t row_num) +{ + writeSpecialRow(columns, row_num, PortKind::Totals, "Totals"); + was_totals_written = true; +} + +void VerticalRowOutputFormat::writeSpecialRow(const Columns & columns, size_t row_num, PortKind port_kind, const char * title) +{ + writeCString("\n", out); + + row_number = 0; + field_number = 0; + + auto & header = getPort(port_kind).getHeader(); + size_t num_columns = columns.size(); + + writeCString(title, out); + writeCString(":\n", out); + + size_t width = strlen(title) + 1; + for (size_t i = 0; i < width; ++i) + writeCString("─", out); + writeChar('\n', out); + + for (size_t i = 0; i < num_columns; ++i) + { + if (i != 0) + writeFieldDelimiter(); + + auto & col = header.getByPosition(i); + writeField(*columns[i], *col.type, row_num); + } +} + +void registerOutputFormatProcessorVertical(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("Vertical", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/VerticalRowOutputFormat.h b/dbms/src/Processors/Formats/Impl/VerticalRowOutputFormat.h new file mode 100644 index 00000000000..a535d1e9c5b --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/VerticalRowOutputFormat.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include + + +namespace DB +{ + +class WriteBuffer; +class Context; + + +/** Stream to output data in format "each value in separate row". + * Usable to show few rows with many columns. + */ +class VerticalRowOutputFormat : public IRowOutputFormat +{ +public: + VerticalRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings); + + String getName() const override { return "VerticalRowOutputFormat"; } + + void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; + void writeRowStartDelimiter() override; + void writeRowBetweenDelimiter() override; + void writeSuffix() override; + + void writeMinExtreme(const Columns & columns, size_t row_num) override; + void writeMaxExtreme(const Columns & columns, size_t row_num) override; + void writeTotals(const Columns & columns, size_t row_num) override; + + void writeBeforeTotals() override; + void writeBeforeExtremes() override; + +protected: + virtual void writeValue(const IColumn & column, const IDataType & type, size_t row_num) const; + + /// For totals and extremes. + void writeSpecialRow(const Columns & columns, size_t row_num, PortKind port_kind, const char * title); + + const FormatSettings format_settings; + size_t field_number = 0; + size_t row_number = 0; + bool was_totals_written = false; + + using NamesAndPaddings = std::vector; + NamesAndPaddings names_and_paddings; +}; + +} + diff --git a/dbms/src/Processors/Formats/Impl/XMLRowOutputFormat.cpp b/dbms/src/Processors/Formats/Impl/XMLRowOutputFormat.cpp new file mode 100644 index 00000000000..5df58a5c733 --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/XMLRowOutputFormat.cpp @@ -0,0 +1,255 @@ +#include +#include +#include +#include + + +namespace DB +{ + +XMLRowOutputFormat::XMLRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings) + : IRowOutputFormat(header, out_), format_settings(format_settings) +{ + auto & sample = getPort(PortKind::Main).getHeader(); + NamesAndTypesList columns(sample.getNamesAndTypesList()); + fields.assign(columns.begin(), columns.end()); + field_tag_names.resize(sample.columns()); + + bool need_validate_utf8 = false; + for (size_t i = 0; i < sample.columns(); ++i) + { + if (!sample.getByPosition(i).type->textCanContainOnlyValidUTF8()) + need_validate_utf8 = true; + + /// As element names, we will use the column name if it has a valid form, or "field", otherwise. + /// The condition below is more strict than the XML standard requires. + bool is_column_name_suitable = true; + const char * begin = fields[i].name.data(); + const char * end = begin + fields[i].name.size(); + for (const char * pos = begin; pos != end; ++pos) + { + char c = *pos; + if (!(isAlphaASCII(c) + || (pos != begin && isNumericASCII(c)) + || c == '_' + || c == '-' + || c == '.')) + { + is_column_name_suitable = false; + break; + } + } + + field_tag_names[i] = is_column_name_suitable + ? fields[i].name + : "field"; + } + + if (need_validate_utf8) + { + validating_ostr = std::make_unique(out); + ostr = validating_ostr.get(); + } + else + ostr = &out; +} + + +void XMLRowOutputFormat::writePrefix() +{ + writeCString("\n", *ostr); + writeCString("\n", *ostr); + writeCString("\t\n", *ostr); + writeCString("\t\t\n", *ostr); + + for (const auto & field : fields) + { + writeCString("\t\t\t\n", *ostr); + + writeCString("\t\t\t\t", *ostr); + writeXMLString(field.name, *ostr); + writeCString("\n", *ostr); + writeCString("\t\t\t\t", *ostr); + writeXMLString(field.type->getName(), *ostr); + writeCString("\n", *ostr); + + writeCString("\t\t\t\n", *ostr); + } + + writeCString("\t\t\n", *ostr); + writeCString("\t\n", *ostr); + writeCString("\t\n", *ostr); +} + + +void XMLRowOutputFormat::writeField(const IColumn & column, const IDataType & type, size_t row_num) +{ + writeCString("\t\t\t<", *ostr); + writeString(field_tag_names[field_number], *ostr); + writeCString(">", *ostr); + type.serializeAsTextXML(column, row_num, *ostr, format_settings); + writeCString("\n", *ostr); + ++field_number; +} + + +void XMLRowOutputFormat::writeRowStartDelimiter() +{ + writeCString("\t\t\n", *ostr); +} + + +void XMLRowOutputFormat::writeRowEndDelimiter() +{ + writeCString("\t\t\n", *ostr); + field_number = 0; + ++row_count; +} + + +void XMLRowOutputFormat::writeSuffix() +{ + writeCString("\t\n", *ostr); + +} + + +void XMLRowOutputFormat::writeBeforeTotals() +{ + writeCString("\t\n", *ostr); +} + +void XMLRowOutputFormat::writeTotals(const Columns & columns, size_t row_num) +{ + size_t totals_columns = columns.size(); + auto & header = getPort(PortKind::Totals).getHeader(); + for (size_t i = 0; i < totals_columns; ++i) + { + const ColumnWithTypeAndName & column = header.safeGetByPosition(i); + + writeCString("\t\t<", *ostr); + writeString(field_tag_names[i], *ostr); + writeCString(">", *ostr); + column.type->serializeAsTextXML(*columns[i], row_num, *ostr, format_settings); + writeCString("\n", *ostr); + } +} + +void XMLRowOutputFormat::writeAfterTotals() +{ + writeCString("\t\n", *ostr); +} + + +void XMLRowOutputFormat::writeBeforeExtremes() +{ + writeCString("\t\n", *ostr); +} + +void XMLRowOutputFormat::writeMinExtreme(const Columns & columns, size_t row_num) +{ + writeExtremesElement("min", columns, row_num); +} + +void XMLRowOutputFormat::writeMaxExtreme(const Columns & columns, size_t row_num) +{ + writeExtremesElement("max", columns, row_num); +} + +void XMLRowOutputFormat::writeAfterExtremes() +{ + writeCString("\t\n", *ostr); +} + +void XMLRowOutputFormat::writeExtremesElement(const char * title, const Columns & columns, size_t row_num) +{ + auto & header = getPort(PortKind::Extremes).getHeader(); + + writeCString("\t\t<", *ostr); + writeCString(title, *ostr); + writeCString(">\n", *ostr); + + size_t extremes_columns = columns.size(); + for (size_t i = 0; i < extremes_columns; ++i) + { + const ColumnWithTypeAndName & column = header.safeGetByPosition(i); + + writeCString("\t\t\t<", *ostr); + writeString(field_tag_names[i], *ostr); + writeCString(">", *ostr); + column.type->serializeAsTextXML(*columns[i], row_num, *ostr, format_settings); + writeCString("\n", *ostr); + } + + writeCString("\t\t\n", *ostr); +} + + +void XMLRowOutputFormat::onProgress(const Progress & value) +{ + progress.incrementPiecewiseAtomically(value); +} + +void XMLRowOutputFormat::writeLastSuffix() +{ + + writeCString("\t", *ostr); + writeIntText(row_count, *ostr); + writeCString("\n", *ostr); + + writeRowsBeforeLimitAtLeast(); + + if (format_settings.write_statistics) + writeStatistics(); + + writeCString("\n", *ostr); + ostr->next(); +} + +void XMLRowOutputFormat::writeRowsBeforeLimitAtLeast() +{ + if (applied_limit) + { + writeCString("\t", *ostr); + writeIntText(rows_before_limit, *ostr); + writeCString("\n", *ostr); + } +} + +void XMLRowOutputFormat::writeStatistics() +{ + writeCString("\t\n", *ostr); + writeCString("\t\t", *ostr); + writeText(watch.elapsedSeconds(), *ostr); + writeCString("\n", *ostr); + writeCString("\t\t", *ostr); + writeText(progress.read_rows.load(), *ostr); + writeCString("\n", *ostr); + writeCString("\t\t", *ostr); + writeText(progress.read_bytes.load(), *ostr); + writeCString("\n", *ostr); + writeCString("\t\n", *ostr); +} + + +void registerOutputFormatProcessorXML(FormatFactory & factory) +{ + factory.registerOutputFormatProcessor("XML", []( + WriteBuffer & buf, + const Block & sample, + const Context &, + const FormatSettings & settings) + { + return std::make_shared(buf, sample, settings); + }); +} + +} diff --git a/dbms/src/Processors/Formats/Impl/XMLRowOutputFormat.h b/dbms/src/Processors/Formats/Impl/XMLRowOutputFormat.h new file mode 100644 index 00000000000..102b11490fe --- /dev/null +++ b/dbms/src/Processors/Formats/Impl/XMLRowOutputFormat.h @@ -0,0 +1,78 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +/** A stream for outputting data in XML format. + */ +class XMLRowOutputFormat : public IRowOutputFormat +{ +public: + XMLRowOutputFormat(WriteBuffer & out_, const Block & header, const FormatSettings & format_settings); + + String getName() const override { return "XMLRowOutputFormat"; } + + void writeField(const IColumn & column, const IDataType & type, size_t row_num) override; + void writeRowStartDelimiter() override; + void writeRowEndDelimiter() override; + void writePrefix() override; + void writeSuffix() override; + void writeLastSuffix() override; + + void writeMinExtreme(const Columns & columns, size_t row_num) override; + void writeMaxExtreme(const Columns & columns, size_t row_num) override; + void writeTotals(const Columns & columns, size_t row_num) override; + + void writeBeforeTotals() override; + void writeAfterTotals() override; + void writeBeforeExtremes() override; + void writeAfterExtremes() override; + + void flush() override + { + ostr->next(); + + if (validating_ostr) + out.next(); + } + + void setRowsBeforeLimit(size_t rows_before_limit_) override + { + applied_limit = true; + rows_before_limit = rows_before_limit_; + } + + void onProgress(const Progress & value) override; + + String getContentType() const override { return "application/xml; charset=UTF-8"; } + +protected: + void writeExtremesElement(const char * title, const Columns & columns, size_t row_num); + void writeRowsBeforeLimitAtLeast(); + void writeStatistics(); + + std::unique_ptr validating_ostr; /// Validates UTF-8 sequences, replaces bad sequences with replacement character. + WriteBuffer * ostr; + + size_t field_number = 0; + size_t row_count = 0; + bool applied_limit = false; + size_t rows_before_limit = 0; + NamesAndTypes fields; + Names field_tag_names; + + Progress progress; + Stopwatch watch; + const FormatSettings format_settings; +}; + +} + diff --git a/dbms/src/Processors/Formats/LazyOutputFormat.cpp b/dbms/src/Processors/Formats/LazyOutputFormat.cpp new file mode 100644 index 00000000000..129d1a06b9d --- /dev/null +++ b/dbms/src/Processors/Formats/LazyOutputFormat.cpp @@ -0,0 +1,61 @@ +#include +#include + + +namespace DB +{ + +WriteBuffer LazyOutputFormat::out(nullptr, 0); + +Block LazyOutputFormat::getBlock(UInt64 milliseconds) +{ + if (finished_processing) + { + if (queue.size() == 0) + return {}; + } + + Chunk chunk; + if (!queue.tryPop(chunk, milliseconds)) + return {}; + + if (!chunk) + return {}; + + auto block = getPort(PortKind::Main).getHeader().cloneWithColumns(chunk.detachColumns()); + info.update(block); + + if (auto chunk_info = chunk.getChunkInfo()) + { + if (auto * agg_info = typeid_cast(chunk_info.get())) + { + block.info.bucket_num = agg_info->bucket_num; + block.info.is_overflows = agg_info->is_overflows; + } + } + + return block; +} + +Block LazyOutputFormat::getTotals() +{ + if (!totals) + return {}; + + return getPort(PortKind::Totals).getHeader().cloneWithColumns(totals.detachColumns()); +} + +Block LazyOutputFormat::getExtremes() +{ + if (!extremes) + return {}; + + return getPort(PortKind::Extremes).getHeader().cloneWithColumns(extremes.detachColumns()); +} + +void LazyOutputFormat::setRowsBeforeLimit(size_t rows_before_limit) +{ + info.setRowsBeforeLimit(rows_before_limit); +} + +} diff --git a/dbms/src/Processors/Formats/LazyOutputFormat.h b/dbms/src/Processors/Formats/LazyOutputFormat.h new file mode 100644 index 00000000000..56aaf249480 --- /dev/null +++ b/dbms/src/Processors/Formats/LazyOutputFormat.h @@ -0,0 +1,64 @@ +#pragma once +#include +#include +#include +#include + +namespace DB +{ + +class LazyOutputFormat : public IOutputFormat +{ + +public: + explicit LazyOutputFormat(const Block & header) + : IOutputFormat(header, out), queue(2), finished_processing(false) {} + + String getName() const override { return "LazyOutputFormat"; } + + Block getBlock(UInt64 milliseconds = 0); + Block getTotals(); + Block getExtremes(); + + bool isFinished() { return finished_processing; } + + BlockStreamProfileInfo & getProfileInfo() { return info; } + + void setRowsBeforeLimit(size_t rows_before_limit) override; + + void finish() { finished_processing = true; } + void clearQueue() { queue.clear(); } + +protected: + void consume(Chunk chunk) override + { + if (!finished_processing) + queue.emplace(std::move(chunk)); + } + + void consumeTotals(Chunk chunk) override { totals = std::move(chunk); } + void consumeExtremes(Chunk chunk) override { extremes = std::move(chunk); } + + void finalize() override + { + finished_processing = true; + + /// In case we are waiting for result. + queue.emplace(Chunk()); + } + +private: + + ConcurrentBoundedQueue queue; + Chunk totals; + Chunk extremes; + + /// Is not used. + static WriteBuffer out; + + BlockStreamProfileInfo info; + + std::atomic finished_processing; +}; + +} diff --git a/dbms/src/Processors/IAccumulatingTransform.cpp b/dbms/src/Processors/IAccumulatingTransform.cpp new file mode 100644 index 00000000000..0abb923584d --- /dev/null +++ b/dbms/src/Processors/IAccumulatingTransform.cpp @@ -0,0 +1,91 @@ +#include + + +namespace DB +{ + +IAccumulatingTransform::IAccumulatingTransform(Block input_header, Block output_header) + : IProcessor({std::move(input_header)}, {std::move(output_header)}), + input(inputs.front()), output(outputs.front()) +{ +} + +IAccumulatingTransform::Status IAccumulatingTransform::prepare() +{ + /// Check can output. + if (output.isFinished()) + { + input.close(); + return Status::Finished; + } + + if (!output.canPush()) + { + input.setNotNeeded(); + return Status::PortFull; + } + + /// Output if has data. + if (current_output_chunk) + output.push(std::move(current_output_chunk)); + + if (finished_generate) + { + output.finish(); + return Status::Finished; + } + + /// Generate output block. + if (input.isFinished()) + { + finished_input = true; + return Status::Ready; + } + + /// Close input if flag was set manually. + if (finished_input) + { + input.close(); + return Status::Ready; + } + + /// Check can input. + if (!has_input) + { + input.setNeeded(); + if (!input.hasData()) + return Status::NeedData; + + current_input_chunk = input.pull(); + has_input = true; + } + + return Status::Ready; +} + +void IAccumulatingTransform::work() +{ + if (!finished_input) + { + consume(std::move(current_input_chunk)); + has_input = false; + } + else + { + current_output_chunk = generate(); + if (!current_output_chunk) + finished_generate = true; + } +} + +void IAccumulatingTransform::setReadyChunk(Chunk chunk) +{ + if (current_output_chunk) + throw Exception("IAccumulatingTransform already has input. Cannot set another chunk. " + "Probably, setReadyChunk method was called twice per consume().", ErrorCodes::LOGICAL_ERROR); + + current_output_chunk = std::move(chunk); +} + +} + diff --git a/dbms/src/Processors/IAccumulatingTransform.h b/dbms/src/Processors/IAccumulatingTransform.h new file mode 100644 index 00000000000..2d3a51f7b2e --- /dev/null +++ b/dbms/src/Processors/IAccumulatingTransform.h @@ -0,0 +1,42 @@ +#pragma once + +#include + + +namespace DB +{ + +/** Has one input and one output. + * Pulls all blocks from input, and only then produce output. + * Examples: ORDER BY, GROUP BY. + */ +class IAccumulatingTransform : public IProcessor +{ +protected: + InputPort & input; + OutputPort & output; + + Chunk current_input_chunk; + Chunk current_output_chunk; + bool has_input = false; + bool finished_input = false; + bool finished_generate = false; + + virtual void consume(Chunk chunk) = 0; + virtual Chunk generate() = 0; + + /// This method can be called once per consume call. In case if some chunks are ready. + void setReadyChunk(Chunk chunk); + void finishConsume() { finished_input = true; } + +public: + IAccumulatingTransform(Block input_header, Block output_header); + + Status prepare() override; + void work() override; + + InputPort & getInputPort() { return input; } + OutputPort & getOutputPort() { return output; } +}; + +} diff --git a/dbms/src/Processors/IInflatingTransform.cpp b/dbms/src/Processors/IInflatingTransform.cpp new file mode 100644 index 00000000000..a1206d52427 --- /dev/null +++ b/dbms/src/Processors/IInflatingTransform.cpp @@ -0,0 +1,85 @@ +#include + +namespace DB +{ + +IInflatingTransform::IInflatingTransform(Block input_header, Block output_header) + : IProcessor({std::move(input_header)}, {std::move(output_header)}) + , input(inputs.front()), output(outputs.front()) +{ + +} + +IInflatingTransform::Status IInflatingTransform::prepare() +{ + /// Check can output. + + if (output.isFinished()) + { + input.close(); + return Status::Finished; + } + + if (!output.canPush()) + { + input.setNotNeeded(); + return Status::PortFull; + } + + /// Output if has data. + if (generated) + { + output.push(std::move(current_chunk)); + generated = false; + } + + if (can_generate) + return Status::Ready; + + /// Check can input. + if (!has_input) + { + if (input.isFinished()) + { + output.finish(); + return Status::Finished; + } + + input.setNeeded(); + + if (!input.hasData()) + return Status::NeedData; + + current_chunk = input.pull(); + has_input = true; + } + + /// Now transform. + return Status::Ready; +} + +void IInflatingTransform::work() +{ + if (can_generate) + { + if (generated) + throw Exception("IInflatingTransform cannot consume chunk because it already was generated", + ErrorCodes::LOGICAL_ERROR); + + current_chunk = generate(); + generated = true; + can_generate = canGenerate(); + } + else + { + if (!has_input) + throw Exception("IInflatingTransform cannot consume chunk because it wasn't read", + ErrorCodes::LOGICAL_ERROR); + + consume(std::move(current_chunk)); + has_input = false; + can_generate = canGenerate(); + } +} + +} diff --git a/dbms/src/Processors/IInflatingTransform.h b/dbms/src/Processors/IInflatingTransform.h new file mode 100644 index 00000000000..45edf5302e5 --- /dev/null +++ b/dbms/src/Processors/IInflatingTransform.h @@ -0,0 +1,32 @@ +#pragma once +#include + +namespace DB +{ + +class IInflatingTransform : public IProcessor +{ +protected: + InputPort & input; + OutputPort & output; + + Chunk current_chunk; + bool has_input = false; + bool generated = false; + bool can_generate = false; + + virtual void consume(Chunk chunk) = 0; + virtual bool canGenerate() = 0; + virtual Chunk generate() = 0; + +public: + IInflatingTransform(Block input_header, Block output_header); + + Status prepare() override; + void work() override; + + InputPort & getInputPort() { return input; } + OutputPort & getOutputPort() { return output; } +}; + +} diff --git a/dbms/src/Processors/IProcessor.cpp b/dbms/src/Processors/IProcessor.cpp new file mode 100644 index 00000000000..36beeea8476 --- /dev/null +++ b/dbms/src/Processors/IProcessor.cpp @@ -0,0 +1,46 @@ +#include +#include + + +namespace DB +{ + +void IProcessor::dump() const +{ + std::cerr << getName() << "\n"; + + std::cerr << "inputs:\n"; + for (const auto & port : inputs) + std::cerr << "\t" << port.hasData() << " " << port.isFinished() << "\n"; + + std::cerr << "outputs:\n"; + for (const auto & port : outputs) + std::cerr << "\t" << port.hasData() << " " << port.isNeeded() << "\n"; +} + + +std::string IProcessor::statusToName(Status status) +{ + switch (status) + { + case Status::NeedData: + return "NeedData"; + case Status::PortFull: + return "PortFull"; + case Status::Finished: + return "Finished"; + case Status::Ready: + return "Ready"; + case Status::Async: + return "Async"; + case Status::Wait: + return "Wait"; + case Status::ExpandPipeline: + return "ExpandPipeline"; + } + + __builtin_unreachable(); +} + +} + diff --git a/dbms/src/Processors/IProcessor.h b/dbms/src/Processors/IProcessor.h new file mode 100644 index 00000000000..c5f9ef64b4a --- /dev/null +++ b/dbms/src/Processors/IProcessor.h @@ -0,0 +1,231 @@ +#pragma once + +#include +#include + + +class EventCounter; + + +namespace DB +{ + +class IProcessor; +using ProcessorPtr = std::shared_ptr; +using Processors = std::vector; + +/** Processor is an element (low level building block) of a query execution pipeline. + * It has zero or more input ports and zero or more output ports. + * + * Blocks of data are transferred over ports. + * Each port has fixed structure: names and types of columns and values of constants. + * + * Processors may pull data from input ports, do some processing and push data to output ports. + * Processor may indicate that it requires input data to proceed and indicate that it needs data from some ports. + * + * Synchronous work must only use CPU - don't do any sleep, IO wait, network wait. + * + * Processor may want to do work asynchronously (example: fetch data from remote server) + * - in this case it will initiate background job and allow to subscribe to it. + * + * Processor may throw an exception to indicate some runtime error. + * + * Different ports may have different structure. For example, ports may correspond to different resultsets + * or semantically different parts of result. + * + * Processor may modify its ports (create another processors and connect to them) on the fly. + * Example: first execute the subquery; on basis of subquery result + * determine how to execute the rest of query and build the corresponding pipeline. + * + * Processor may simply wait for another processor to execute without transferring any data from it. + * For this purpose it should connect its input port to another processor, and indicate need of data. + * + * Examples: + * + * Source. Has no input ports and single output port. Generates data itself and pushes it to its output port. + * + * Sink. Has single input port and no output ports. Consumes data that was passed to its input port. + * + * Empty source. Immediately says that data on its output port is finished. + * + * Null sink. Consumes data and does nothing. + * + * Simple transformation. Has single input and single output port. Pulls data, transforms it and pushes to output port. + * Example: expression calculator. + * TODO Better to make each function a separate processor. It's better for pipeline analysis. Also keep in mind 'sleep' and 'rand' functions. + * + * Squashing or filtering transformation. Pulls data, possibly accumulates it, and sometimes pushes it to output port. + * Examples: DISTINCT, WHERE, squashing of blocks for INSERT SELECT. + * + * Accumulating transformation. Pulls and accumulates all data from input until it it exhausted, then pushes data to output port. + * Examples: ORDER BY, GROUP BY. + * + * Limiting transformation. Pulls data from input and passes to output. + * When there was enough data, says that it doesn't need data on its input and that data on its output port is finished. + * + * Resize. Has arbitary number of inputs and arbitary number of outputs. + * Pulls data from whatever ready input and pushes it to randomly choosed free output. + * Examples: + * Union - merge data from number of inputs to one output in arbitary order. + * Split - read data from one input and pass it to arbitary output. + * + * Concat. Has many inputs and only one output. Pulls all data from first input until it is exhausted, + * then all data from second input, etc. and pushes all data to output. + * + * Ordered merge. Has many inputs but only one output. Pulls data from selected input in specific order, merges and pushes it to output. + * + * Fork. Has one input and many outputs. Pulls data from input and copies it to all outputs. + * Used to process multiple queries with common source of data. + * + * Select. Has one or multiple inputs and one output. + * Read blocks from inputs and check that blocks on inputs are "parallel": correspond to each other in number of rows. + * Construct a new block by selecting some subset (or all) of columns from inputs. + * Example: collect columns - function arguments before function execution. + * + * + * TODO Processors may carry algebraic properties about transformations they do. + * For example, that processor doesn't change number of rows; doesn't change order of rows, doesn't change the set of rows, etc. + * + * TODO Ports may carry algebraic properties about streams of data. + * For example, that data comes ordered by specific key; or grouped by specific key; or have unique values of specific key. + * And also simple properties, including lower and upper bound on number of rows. + * + * TODO Processor should have declarative representation, that is able to be serialized and parsed. + * Example: read_from_merge_tree(database, table, Columns(a, b, c), Piece(0, 10), Parts(Part('name', MarkRanges(MarkRange(0, 100), ...)), ...)) + * It's reasonable to have an intermediate language for declaration of pipelines. + * + * TODO Processor with all its parameters should represent "pure" function on streams of data from its input ports. + * It's in question, what kind of "pure" function do we mean. + * For example, data streams are considered equal up to order unless ordering properties are stated explicitly. + * Another example: we should support the notion of "arbitary N-th of M substream" of full stream of data. + */ + +class IProcessor +{ +protected: + InputPorts inputs; + OutputPorts outputs; + +public: + IProcessor() = default; + + IProcessor(InputPorts inputs_, OutputPorts outputs_) + : inputs(std::move(inputs_)), outputs(std::move(outputs_)) + { + for (auto & port : inputs) + port.processor = this; + for (auto & port : outputs) + port.processor = this; + } + + virtual String getName() const = 0; + + enum class Status + { + /// Processor needs some data at its inputs to proceed. + /// You need to run another processor to generate required input and then call 'prepare' again. + NeedData, + + /// Processor cannot proceed because output port is full or not isNeeded(). + /// You need to transfer data from output port to the input port of another processor and then call 'prepare' again. + PortFull, + + /// All work is done (all data is processed or all output are closed), nothing more to do. + Finished, + + /// No one needs data on output ports. + /// Unneeded, + + /// You may call 'work' method and processor will do some work synchronously. + Ready, + + /// You may call 'schedule' method and processor will initiate some background work. + Async, + + /// Processor is doing some work in background. + /// You may wait for next event or do something else and then you should call 'prepare' again. + Wait, + + /// Processor wants to add other processors to pipeline. + /// New processors must be obtained by expandPipeline() call. + ExpandPipeline, + }; + + static std::string statusToName(Status status); + + /** Method 'prepare' is responsible for all cheap ("instantenous": O(1) of data volume, no wait) calculations. + * + * It may access input and output ports, + * indicate the need for work by another processor by returning NeedData or PortFull, + * or indicate the absense of work by returning Finished or Unneeded, + * it may pull data from input ports and push data to output ports. + * + * The method is not thread-safe and must be called from a single thread in one moment of time, + * even for different connected processors. + * + * Instead of all long work (CPU calculations or waiting) it should just prepare all required data and return Ready or Async. + * + * Thread safety and parallel execution: + * - no methods (prepare, work, schedule) of single object can be executed in parallel; + * - method 'work' can be executed in parallel for different objects, even for connected processors; + * - method 'prepare' cannot be executed in parallel even for different objects, + * if they are connected (including indirectly) to each other by their ports; + */ + virtual Status prepare() = 0; + + /** You may call this method if 'prepare' returned Ready. + * This method cannot access any ports. It should use only data that was prepared by 'prepare' method. + * + * Method work can be executed in parallel for different processors. + */ + virtual void work() + { + throw Exception("Method 'work' is not implemented for " + getName() + " processor", ErrorCodes::NOT_IMPLEMENTED); + } + + /** You may call this method if 'prepare' returned Async. + * This method cannot access any ports. It should use only data that was prepared by 'prepare' method. + * + * This method should return instantly and fire an event (or many events) when asynchronous job will be done. + * When the job is not done, method 'prepare' will return Wait and the user may block and wait for next event before checking again. + * + * Note that it can fire many events in EventCounter while doing its job, + * and you have to wait for next event (or do something else) every time when 'prepare' returned Wait. + */ + virtual void schedule(EventCounter & /*watch*/) + { + throw Exception("Method 'schedule' is not implemented for " + getName() + " processor", ErrorCodes::NOT_IMPLEMENTED); + } + + /** You must call this method if 'prepare' returned ExpandPipeline. + * This method cannot access any port, but it can create new ports for current processor. + * + * Method should return set of new already connected processors. + * All added processors must be connected only to each other or current processor. + * + * Method can't remove or reconnect existing ports, move data from/to port or perform calculations. + * 'prepare' should be called again after expanding pipeline. + */ + virtual Processors expandPipeline() + { + throw Exception("Method 'expandPipeline' is not implemented for " + getName() + " processor", ErrorCodes::NOT_IMPLEMENTED); + } + + virtual ~IProcessor() = default; + + auto & getInputs() { return inputs; } + auto & getOutputs() { return outputs; } + + /// Debug output. + void dump() const; + + std::string processor_description; + + void setDescription(const std::string & description_) { processor_description = description_; } + const std::string & getDescription() const { return processor_description; } +}; + + + + +} diff --git a/dbms/src/Processors/ISimpleTransform.cpp b/dbms/src/Processors/ISimpleTransform.cpp new file mode 100644 index 00000000000..39736973a16 --- /dev/null +++ b/dbms/src/Processors/ISimpleTransform.cpp @@ -0,0 +1,109 @@ +#include + + +namespace DB +{ + +ISimpleTransform::ISimpleTransform(Block input_header, Block output_header, bool skip_empty_chunks) + : IProcessor({std::move(input_header)}, {std::move(output_header)}) + , input(inputs.front()) + , output(outputs.front()) + , skip_empty_chunks(skip_empty_chunks) +{ +} + +ISimpleTransform::Status ISimpleTransform::prepare() +{ + /// Check can output. + + if (output.isFinished()) + { + input.close(); + return Status::Finished; + } + + if (!output.canPush()) + { + input.setNotNeeded(); + return Status::PortFull; + } + + /// Output if has data. + if (transformed) + { + output.pushData(std::move(current_data)); + transformed = false; + } + + /// Stop if don't need more data. + if (no_more_data_needed) + { + input.close(); + output.finish(); + return Status::Finished; + } + + /// Check can input. + if (!has_input) + { + if (input.isFinished()) + { + output.finish(); + return Status::Finished; + } + + input.setNeeded(); + + if (!input.hasData()) + return Status::NeedData; + + current_data = input.pullData(); + has_input = true; + + if (current_data.exception) + { + /// Skip transform in case of exception. + has_input = false; + transformed = true; + + /// No more data needed. Exception will be thrown (or swallowed) later. + input.setNotNeeded(); + } + + if (set_input_not_needed_after_read) + input.setNotNeeded(); + } + + /// Now transform. + return Status::Ready; +} + +void ISimpleTransform::work() +{ + if (current_data.exception) + return; + + try + { + transform(current_data.chunk); + } + catch (DB::Exception &) + { + current_data.exception = std::current_exception(); + transformed = true; + has_input = false; + return; + } + + has_input = false; + + if (!skip_empty_chunks || current_data.chunk) + transformed = true; + + if (transformed && !current_data.chunk) + /// Support invariant that chunks must have the same number of columns as header. + current_data.chunk = Chunk(getOutputPort().getHeader().cloneEmpty().getColumns(), 0); +} + +} + diff --git a/dbms/src/Processors/ISimpleTransform.h b/dbms/src/Processors/ISimpleTransform.h new file mode 100644 index 00000000000..82e383ceeb0 --- /dev/null +++ b/dbms/src/Processors/ISimpleTransform.h @@ -0,0 +1,44 @@ +#pragma once + +#include + + +namespace DB +{ + +/** Has one input and one output. + * Simply pull a block from input, transform it, and push it to output. + */ +class ISimpleTransform : public IProcessor +{ +protected: + InputPort & input; + OutputPort & output; + + Port::Data current_data; + bool has_input = false; + bool transformed = false; + bool no_more_data_needed = false; + const bool skip_empty_chunks; + + /// Set input port NotNeeded after chunk was pulled. + /// Input port will become needed again only after data was transformed. + /// This allows to escape caching chunks in input port, which can lead to uneven data distribution. + bool set_input_not_needed_after_read = false; + + virtual void transform(Chunk & chunk) = 0; + void stopReading() { no_more_data_needed = true; } + +public: + ISimpleTransform(Block input_header, Block output_header, bool skip_empty_chunks); + + Status prepare() override; + void work() override; + + InputPort & getInputPort() { return input; } + OutputPort & getOutputPort() { return output; } + + void setInputNotNeededAfterRead(bool value) { set_input_not_needed_after_read = value; } +}; + +} diff --git a/dbms/src/Processors/ISink.cpp b/dbms/src/Processors/ISink.cpp new file mode 100644 index 00000000000..5c5f98cb131 --- /dev/null +++ b/dbms/src/Processors/ISink.cpp @@ -0,0 +1,36 @@ +#include + + +namespace DB +{ + +ISink::ISink(Block header) + : IProcessor({std::move(header)}, {}), input(inputs.front()) +{ +} + +ISink::Status ISink::prepare() +{ + if (has_input) + return Status::Ready; + + if (input.isFinished()) + return Status::Finished; + + input.setNeeded(); + if (!input.hasData()) + return Status::NeedData; + + current_chunk = input.pull(); + has_input = true; + return Status::Ready; +} + +void ISink::work() +{ + consume(std::move(current_chunk)); + has_input = false; +} + +} + diff --git a/dbms/src/Processors/ISink.h b/dbms/src/Processors/ISink.h new file mode 100644 index 00000000000..4e25e528098 --- /dev/null +++ b/dbms/src/Processors/ISink.h @@ -0,0 +1,27 @@ +#pragma once + +#include + + +namespace DB +{ + +class ISink : public IProcessor +{ +protected: + InputPort & input; + Chunk current_chunk; + bool has_input = false; + + virtual void consume(Chunk block) = 0; + +public: + explicit ISink(Block header); + + Status prepare() override; + void work() override; + + InputPort & getPort() { return input; } +}; + +} diff --git a/dbms/src/Processors/ISource.cpp b/dbms/src/Processors/ISource.cpp new file mode 100644 index 00000000000..d40f0e32fb7 --- /dev/null +++ b/dbms/src/Processors/ISource.cpp @@ -0,0 +1,67 @@ +#include + + +namespace DB +{ + +ISource::ISource(Block header) + : IProcessor({}, {std::move(header)}), output(outputs.front()) +{ +} + +ISource::Status ISource::prepare() +{ + if (finished) + { + output.finish(); + return Status::Finished; + } + + /// Check can output. + if (output.isFinished()) + return Status::Finished; + + if (!output.canPush()) + return Status::PortFull; + + if (!has_input) + return Status::Ready; + + output.pushData(std::move(current_chunk)); + has_input = false; + + if (got_exception) + { + finished = true; + output.finish(); + return Status::Finished; + } + + /// Now, we pushed to output, and it must be full. + return Status::PortFull; +} + +void ISource::work() +{ + try + { + current_chunk.chunk = generate(); + if (!current_chunk.chunk) + finished = true; + else + has_input = true; + } + catch (...) + { + finished = true; + throw; + } +// { +// current_chunk = std::current_exception(); +// has_input = true; +// got_exception = true; +// } +} + +} + diff --git a/dbms/src/Processors/ISource.h b/dbms/src/Processors/ISource.h new file mode 100644 index 00000000000..b1669860192 --- /dev/null +++ b/dbms/src/Processors/ISource.h @@ -0,0 +1,30 @@ +#pragma once + +#include + + +namespace DB +{ + +class ISource : public IProcessor +{ +protected: + OutputPort & output; + bool has_input = false; + bool finished = false; + bool got_exception = false; + Port::Data current_chunk; + + virtual Chunk generate() = 0; + +public: + ISource(Block header); + + Status prepare() override; + void work() override; + + OutputPort & getPort() { return output; } + const OutputPort & getPort() const { return output; } +}; + +} diff --git a/dbms/src/Processors/LimitTransform.cpp b/dbms/src/Processors/LimitTransform.cpp new file mode 100644 index 00000000000..f591ecfb046 --- /dev/null +++ b/dbms/src/Processors/LimitTransform.cpp @@ -0,0 +1,159 @@ +#include + + +namespace DB +{ + +LimitTransform::LimitTransform( + const Block & header, size_t limit, size_t offset, + bool always_read_till_end) + : IProcessor({header}, {header}) + , input(inputs.front()), output(outputs.front()) + , limit(limit), offset(offset) + , always_read_till_end(always_read_till_end) +{ +} + + +LimitTransform::Status LimitTransform::prepare() +{ + + + /// Check can output. + bool output_finished = false; + if (output.isFinished()) + { + output_finished = true; + if (!always_read_till_end) + { + input.close(); + return Status::Finished; + } + } + + if (!output_finished && !output.canPush()) + { + input.setNotNeeded(); + return Status::PortFull; + } + + /// Push block if can. + if (!output_finished && has_block && block_processed) + { + output.push(std::move(current_chunk)); + has_block = false; + block_processed = false; + } + + /// Check if we are done with pushing. + bool pushing_is_finished = rows_read >= offset + limit; + if (pushing_is_finished) + { + if (!always_read_till_end) + { + output.finish(); + input.close(); + return Status::Finished; + } + } + + /// Check can input. + + if (input.isFinished()) + { + output.finish(); + return Status::Finished; + } + + input.setNeeded(); + if (!input.hasData()) + return Status::NeedData; + + current_chunk = input.pull(); + has_block = true; + + auto rows = current_chunk.getNumRows(); + rows_before_limit_at_least += rows; + + /// Skip block (for 'always_read_till_end' case). + if (pushing_is_finished) + { + current_chunk.clear(); + has_block = false; + + if (input.isFinished()) + { + output.finish(); + return Status::Finished; + } + + /// Now, we pulled from input, and it must be empty. + return Status::NeedData; + } + + /// Process block. + + rows_read += rows; + + if (rows_read <= offset) + { + current_chunk.clear(); + has_block = false; + + if (input.isFinished()) + { + output.finish(); + return Status::Finished; + } + + /// Now, we pulled from input, and it must be empty. + return Status::NeedData; + } + + /// Return the whole block. + if (rows_read >= offset + rows && rows_read <= offset + limit) + { + if (output.hasData()) + return Status::PortFull; + + output.push(std::move(current_chunk)); + has_block = false; + + return Status::PortFull; + } + + /// No more data is needed. + if (!always_read_till_end && rows_read >= offset + limit) + input.close(); + + return Status::Ready; +} + + +void LimitTransform::work() +{ + size_t num_rows = current_chunk.getNumRows(); + size_t num_columns = current_chunk.getNumColumns(); + + /// return a piece of the block + size_t start = std::max( + static_cast(0), + static_cast(offset) - static_cast(rows_read) + static_cast(num_rows)); + + size_t length = std::min( + static_cast(limit), std::min( + static_cast(rows_read) - static_cast(offset), + static_cast(limit) + static_cast(offset) - static_cast(rows_read) + static_cast(num_rows))); + + auto columns = current_chunk.detachColumns(); + + for (size_t i = 0; i < num_columns; ++i) + columns[i] = columns[i]->cut(start, length); + + current_chunk.setColumns(std::move(columns), length); + + block_processed = true; +} + +} + diff --git a/dbms/src/Processors/LimitTransform.h b/dbms/src/Processors/LimitTransform.h new file mode 100644 index 00000000000..eb5a8fe8d5a --- /dev/null +++ b/dbms/src/Processors/LimitTransform.h @@ -0,0 +1,42 @@ +#pragma once + +#include + + +namespace DB +{ + +class LimitTransform : public IProcessor +{ +private: + InputPort & input; + OutputPort & output; + + size_t limit; + size_t offset; + size_t rows_read = 0; /// including the last read block + bool always_read_till_end; + + bool has_block = false; + bool block_processed = false; + Chunk current_chunk; + + UInt64 rows_before_limit_at_least = 0; + +public: + LimitTransform( + const Block & header, size_t limit, size_t offset, + bool always_read_till_end = false); + + String getName() const override { return "Limit"; } + + Status prepare() override; + void work() override; + + InputPort & getInputPort() { return input; } + OutputPort & getOutputPort() { return output; } + + UInt64 getRowsBeforeLimitAtLeast() const { return rows_before_limit_at_least; } +}; + +} diff --git a/dbms/src/Processors/NullSink.h b/dbms/src/Processors/NullSink.h new file mode 100644 index 00000000000..e4968daee29 --- /dev/null +++ b/dbms/src/Processors/NullSink.h @@ -0,0 +1,22 @@ +#pragma once +#include + +namespace DB +{ + +class NullSink : public IProcessor +{ +public: + explicit NullSink(Block header) : IProcessor({std::move(header)}, {}) {} + String getName() const override { return "NullSink"; } + + Status prepare() override + { + inputs.front().close(); + return Status::Finished; + } + + InputPort & getPort() { return inputs.front(); } +}; + +} diff --git a/dbms/src/Processors/Port.cpp b/dbms/src/Processors/Port.cpp new file mode 100644 index 00000000000..43f901aa4b9 --- /dev/null +++ b/dbms/src/Processors/Port.cpp @@ -0,0 +1,23 @@ +#include +#include + +namespace DB +{ + +void connect(OutputPort & output, InputPort & input) +{ + if (input.state || output.state) + throw Exception("Port is already connected", ErrorCodes::LOGICAL_ERROR); + + auto out_name = output.getProcessor().getName(); + auto in_name = input.getProcessor().getName(); + + assertBlocksHaveEqualStructure(input.getHeader(), output.getHeader(), " function connect between " + out_name + " and " + in_name); + + input.output_port = &output; + output.input_port = &input; + input.state = std::make_shared(); + output.state = input.state; +} + +} diff --git a/dbms/src/Processors/Port.h b/dbms/src/Processors/Port.h new file mode 100644 index 00000000000..99ad7df4b50 --- /dev/null +++ b/dbms/src/Processors/Port.h @@ -0,0 +1,430 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace DB +{ + +class InputPort; +class OutputPort; +class IProcessor; + + +class Port +{ + friend void connect(OutputPort &, InputPort &); + friend class IProcessor; + +protected: + /// Shared state of two connected ports. + class State + { + public: + + struct Data + { + /// Note: std::variant can be used. But move constructor for it can't be inlined. + Chunk chunk; + std::exception_ptr exception; + }; + + private: + static std::uintptr_t getUInt(Data * data) { return reinterpret_cast(data); } + static Data * getPtr(std::uintptr_t data) { return reinterpret_cast(data); } + + public: + + /// Flags for Port state. + /// Will store them in least pointer bits. + + /// Port was set finished or closed. + static constexpr std::uintptr_t IS_FINISHED = 1; + /// Block is not needed right now, but may be will be needed later. + /// This allows to pause calculations if we are not sure that we need more data. + static constexpr std::uintptr_t IS_NEEDED = 2; + /// Check if port has data. + static constexpr std::uintptr_t HAS_DATA = 4; + + static constexpr std::uintptr_t FLAGS_MASK = IS_FINISHED | IS_NEEDED | HAS_DATA; + static constexpr std::uintptr_t PTR_MASK = ~FLAGS_MASK; + + /// Tiny smart ptr class for Data. Takes into account that ptr can have flags in least bits. + class DataPtr + { + public: + DataPtr() : data(new Data()) + { + if (unlikely((getUInt(data) & FLAGS_MASK) != 0)) + throw Exception("Not alignment memory for Port.", ErrorCodes::LOGICAL_ERROR); + } + /// Pointer can store flags in case of exception in swap. + ~DataPtr() { delete getPtr(getUInt(data) & PTR_MASK); } + + DataPtr(DataPtr const &) : data(new Data()) {} + DataPtr& operator=(DataPtr const &) = delete; + + Data * operator->() const { return data; } + Data & operator*() const { return *data; } + + Data * get() const { return data; } + explicit operator bool() const { return data; } + + Data * release() + { + Data * result = nullptr; + std::swap(result, data); + return result; + } + + uintptr_t ALWAYS_INLINE swap(std::atomic & value, std::uintptr_t flags, std::uintptr_t mask) + { + Data * expected = nullptr; + Data * desired = getPtr(flags | getUInt(data)); + + while (!value.compare_exchange_weak(expected, desired)) + desired = getPtr((getUInt(expected) & FLAGS_MASK & (~mask)) | flags | getUInt(data)); + + /// It's not very safe. In case of exception after exchange and before assigment we will get leak. + /// Don't know how to make it better. + data = getPtr(getUInt(expected) & PTR_MASK); + + return getUInt(expected) & FLAGS_MASK; + } + + private: + Data * data = nullptr; + }; + + /// Not finished, not needed, has not data. + State() : data(new Data()) + { + if (unlikely((getUInt(data) & FLAGS_MASK) != 0)) + throw Exception("Not alignment memory for Port.", ErrorCodes::LOGICAL_ERROR); + } + + ~State() + { + Data * desired = nullptr; + Data * expected = nullptr; + + while (!data.compare_exchange_weak(expected, desired)); + + expected = getPtr(getUInt(expected) & PTR_MASK); + delete expected; + } + + void ALWAYS_INLINE push(DataPtr & data_, std::uintptr_t & flags) + { + flags = data_.swap(data, HAS_DATA, HAS_DATA); + + /// It's possible to push data into finished port. Will just ignore it. + /// if (flags & IS_FINISHED) + /// throw Exception("Cannot push block to finished port.", ErrorCodes::LOGICAL_ERROR); + + /// It's possible to push data into port which is not needed now. + /// if ((flags & IS_NEEDED) == 0) + /// throw Exception("Cannot push block to port which is not needed.", ErrorCodes::LOGICAL_ERROR); + + if (unlikely(flags & HAS_DATA)) + throw Exception("Cannot push block to port which already has data.", ErrorCodes::LOGICAL_ERROR); + } + + void ALWAYS_INLINE pull(DataPtr & data_, std::uintptr_t & flags) + { + flags = data_.swap(data, 0, HAS_DATA); + + /// It's ok to check because this flag can be changed only by pulling thread. + if (unlikely((flags & IS_NEEDED) == 0)) + throw Exception("Cannot pull block from port which is not needed.", ErrorCodes::LOGICAL_ERROR); + + if (unlikely((flags & HAS_DATA) == 0)) + throw Exception("Cannot pull block from port which has no data.", ErrorCodes::LOGICAL_ERROR); + } + + std::uintptr_t ALWAYS_INLINE setFlags(std::uintptr_t flags, std::uintptr_t mask) + { + Data * expected = nullptr; + Data * desired = getPtr(flags); + + while (!data.compare_exchange_weak(expected, desired)) + desired = getPtr((getUInt(expected) & FLAGS_MASK & (~mask)) | flags | (getUInt(expected) & PTR_MASK)); + + return getUInt(expected) & FLAGS_MASK; + } + + std::uintptr_t ALWAYS_INLINE getFlags() const + { + return getUInt(data.load()) & FLAGS_MASK; + } + + private: + std::atomic data; + }; + + Block header; + std::shared_ptr state; + + /// This object is only used for data exchange between port and shared state. + State::DataPtr data; + + IProcessor * processor = nullptr; + +public: + using Data = State::Data; + + Port(Block header) : header(std::move(header)) {} + Port(Block header, IProcessor * processor) : header(std::move(header)), processor(processor) {} + + const Block & getHeader() const { return header; } + bool ALWAYS_INLINE isConnected() const { return state != nullptr; } + + void ALWAYS_INLINE assumeConnected() const + { + if (unlikely(!isConnected())) + throw Exception("Port is not connected", ErrorCodes::LOGICAL_ERROR); + } + + bool ALWAYS_INLINE hasData() const + { + assumeConnected(); + return state->getFlags() & State::HAS_DATA; + } + + IProcessor & getProcessor() + { + if (!processor) + throw Exception("Port does not belong to Processor", ErrorCodes::LOGICAL_ERROR); + return *processor; + } + + const IProcessor & getProcessor() const + { + if (!processor) + throw Exception("Port does not belong to Processor", ErrorCodes::LOGICAL_ERROR); + return *processor; + } +}; + +/// Invariants: +/// * If you close port, it isFinished(). +/// * If port isFinished(), you can do nothing with it. +/// * If port is not needed, you can only setNeeded() or close() it. +/// * You can pull only if port hasData(). +class InputPort : public Port +{ + friend void connect(OutputPort &, InputPort &); + +private: + OutputPort * output_port = nullptr; + + /// If version was set, it will be increased on each pull. + UInt64 * version = nullptr; + + mutable bool is_finished = false; + +public: + using Port::Port; + + void setVersion(UInt64 * value) { version = value; } + + Data ALWAYS_INLINE pullData() + { + if (version) + ++(*version); + + assumeConnected(); + + std::uintptr_t flags = 0; + state->pull(data, flags); + + is_finished = flags & State::IS_FINISHED; + + if (unlikely(!data->exception && data->chunk.getNumColumns() != header.columns())) + { + auto & chunk = data->chunk; + + String msg = "Invalid number of columns in chunk pulled from OutputPort. Expected " + + std::to_string(header.columns()) + ", found " + std::to_string(chunk.getNumColumns()) + '\n'; + + msg += "Header: " + header.dumpStructure() + '\n'; + msg += "Chunk: " + chunk.dumpStructure() + '\n'; + + throw Exception(msg, ErrorCodes::LOGICAL_ERROR); + } + + return std::move(*data); + } + + Chunk ALWAYS_INLINE pull() + { + auto data_ = pullData(); + + if (data_.exception) + std::rethrow_exception(data_.exception); + + return std::move(data_.chunk); + } + + bool ALWAYS_INLINE isFinished() const + { + assumeConnected(); + + if (is_finished) + return true; + + auto flags = state->getFlags(); + + is_finished = (flags & State::IS_FINISHED) && ((flags & State::HAS_DATA) == 0); + + return is_finished; + } + + void ALWAYS_INLINE setNeeded() + { + assumeConnected(); + + if ((state->setFlags(State::IS_NEEDED, State::IS_NEEDED) & State::IS_NEEDED) == 0 && version) + ++(*version); + } + + void ALWAYS_INLINE setNotNeeded() + { + assumeConnected(); + state->setFlags(0, State::IS_NEEDED); + } + + void ALWAYS_INLINE close() + { + assumeConnected(); + + if ((state->setFlags(State::IS_FINISHED, State::IS_FINISHED) & State::IS_FINISHED) == 0 && version) + ++(*version); + + is_finished = true; + } + + OutputPort & getOutputPort() + { + assumeConnected(); + return *output_port; + } + + const OutputPort & getOutputPort() const + { + assumeConnected(); + return *output_port; + } +}; + + +/// Invariants: +/// * If you finish port, it isFinished(). +/// * If port isFinished(), you can do nothing with it. +/// * If port not isNeeded(), you can only finish() it. +/// * You can hush only if port doesn't hasData(). +class OutputPort : public Port +{ + friend void connect(OutputPort &, InputPort &); + +private: + InputPort * input_port = nullptr; + + /// If version was set, it will be increased on each push. + UInt64 * version = nullptr; + +public: + using Port::Port; + + void setVersion(UInt64 * value) { version = value; } + + void ALWAYS_INLINE push(Chunk chunk) + { + pushData({.chunk = std::move(chunk), .exception = {}}); + } + + void ALWAYS_INLINE push(std::exception_ptr exception) + { + pushData({.chunk = {}, .exception = std::move(exception)}); + } + + void ALWAYS_INLINE pushData(Data data_) + { + if (unlikely(!data_.exception && data_.chunk.getNumColumns() != header.columns())) + { + String msg = "Invalid number of columns in chunk pushed to OutputPort. Expected " + + std::to_string(header.columns()) + + ", found " + std::to_string(data_.chunk.getNumColumns()) + '\n'; + + msg += "Header: " + header.dumpStructure() + '\n'; + msg += "Chunk: " + data_.chunk.dumpStructure() + '\n'; + + throw Exception(msg, ErrorCodes::LOGICAL_ERROR); + } + + if (version) + ++(*version); + + assumeConnected(); + + std::uintptr_t flags = 0; + *data = std::move(data_); + state->push(data, flags); + } + + void ALWAYS_INLINE finish() + { + assumeConnected(); + + auto flags = state->setFlags(State::IS_FINISHED, State::IS_FINISHED); + + if (version && (flags & State::IS_FINISHED) == 0) + ++(*version); + } + + bool ALWAYS_INLINE isNeeded() const + { + assumeConnected(); + return state->getFlags() & State::IS_NEEDED; + } + + bool ALWAYS_INLINE isFinished() const + { + assumeConnected(); + return state->getFlags() & State::IS_FINISHED; + } + + bool ALWAYS_INLINE canPush() const + { + assumeConnected(); + auto flags = state->getFlags(); + return (flags & State::IS_NEEDED) && ((flags & State::HAS_DATA) == 0); + } + + InputPort & getInputPort() + { + assumeConnected(); + return *input_port; + } + + const InputPort & getInputPort() const + { + assumeConnected(); + return *input_port; + } +}; + + +using InputPorts = std::list; +using OutputPorts = std::list; + + +void connect(OutputPort & output, InputPort & input); + +} diff --git a/dbms/src/Processors/QueryPipeline.cpp b/dbms/src/Processors/QueryPipeline.cpp new file mode 100644 index 00000000000..cb9be19088c --- /dev/null +++ b/dbms/src/Processors/QueryPipeline.cpp @@ -0,0 +1,634 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace DB +{ + +void QueryPipeline::checkInitialized() +{ + if (!initialized()) + throw Exception("QueryPipeline wasn't initialized.", ErrorCodes::LOGICAL_ERROR); +} + +void QueryPipeline::checkSource(const ProcessorPtr & source, bool can_have_totals) +{ + if (!source->getInputs().empty()) + throw Exception("Source for query pipeline shouldn't have any input, but " + source->getName() + " has " + + toString(source->getInputs().size()) + " inputs.", ErrorCodes::LOGICAL_ERROR); + + if (source->getOutputs().empty()) + throw Exception("Source for query pipeline should have single output, but it doesn't have any", + ErrorCodes::LOGICAL_ERROR); + + if (!can_have_totals && source->getOutputs().size() != 1) + throw Exception("Source for query pipeline should have single output, but " + source->getName() + " has " + + toString(source->getOutputs().size()) + " outputs.", ErrorCodes::LOGICAL_ERROR); + + if (source->getOutputs().size() > 2) + throw Exception("Source for query pipeline should have 1 or 2 outputs, but " + source->getName() + " has " + + toString(source->getOutputs().size()) + " outputs.", ErrorCodes::LOGICAL_ERROR); +} + +void QueryPipeline::init(Processors sources) +{ + if (initialized()) + throw Exception("Pipeline has already been initialized.", ErrorCodes::LOGICAL_ERROR); + + if (sources.empty()) + throw Exception("Can't initialize pipeline with empty source list.", ErrorCodes::LOGICAL_ERROR); + + std::vector totals; + + for (auto & source : sources) + { + checkSource(source, true); + + auto & header = source->getOutputs().front().getHeader(); + + if (current_header) + assertBlocksHaveEqualStructure(current_header, header, "QueryPipeline"); + else + current_header = header; + + if (source->getOutputs().size() > 1) + { + assertBlocksHaveEqualStructure(current_header, source->getOutputs().back().getHeader(), "QueryPipeline"); + totals.emplace_back(&source->getOutputs().back()); + } + + streams.emplace_back(&source->getOutputs().front()); + processors.emplace_back(std::move(source)); + } + + if (!totals.empty()) + { + if (totals.size() == 1) + totals_having_port = totals.back(); + else + { + auto resize = std::make_shared(current_header, totals.size(), 1); + auto in = resize->getInputs().begin(); + for (auto & total : totals) + connect(*total, *(in++)); + + totals_having_port = &resize->getOutputs().front(); + processors.emplace_back(std::move(resize)); + } + } +} + +static ProcessorPtr callProcessorGetter( + const Block & header, const QueryPipeline::ProcessorGetter & getter, QueryPipeline::StreamType) +{ + return getter(header); +} + +static ProcessorPtr callProcessorGetter( + const Block & header, const QueryPipeline::ProcessorGetterWithStreamKind & getter, QueryPipeline::StreamType kind) +{ + return getter(header, kind); +} + +template +void QueryPipeline::addSimpleTransformImpl(const TProcessorGetter & getter) +{ + checkInitialized(); + + Block header; + + auto add_transform = [&](OutputPort *& stream, StreamType stream_type) + { + if (!stream) + return; + + auto transform = callProcessorGetter(stream->getHeader(), getter, stream_type); + + if (transform) + { + if (transform->getInputs().size() != 1) + throw Exception("Processor for query pipeline transform should have single input, " + "but " + transform->getName() + " has " + + toString(transform->getInputs().size()) + " inputs.", ErrorCodes::LOGICAL_ERROR); + + if (transform->getOutputs().size() != 1) + throw Exception("Processor for query pipeline transform should have single output, " + "but " + transform->getName() + " has " + + toString(transform->getOutputs().size()) + " outputs.", ErrorCodes::LOGICAL_ERROR); + } + + auto & out_header = transform ? transform->getOutputs().front().getHeader() + : stream->getHeader(); + + if (stream_type != StreamType::Totals) + { + if (header) + assertBlocksHaveEqualStructure(header, out_header, "QueryPipeline"); + else + header = out_header; + } + + if (transform) + { + connect(*stream, transform->getInputs().front()); + stream = &transform->getOutputs().front(); + processors.emplace_back(std::move(transform)); + } + }; + + for (auto & stream : streams) + add_transform(stream, StreamType::Main); + + add_transform(delayed_stream_port, StreamType::Main); + add_transform(totals_having_port, StreamType::Totals); + add_transform(extremes_port, StreamType::Extremes); + + current_header = std::move(header); +} + +void QueryPipeline::addSimpleTransform(const ProcessorGetter & getter) +{ + addSimpleTransformImpl(getter); +} + +void QueryPipeline::addSimpleTransform(const ProcessorGetterWithStreamKind & getter) +{ + addSimpleTransformImpl(getter); +} + +void QueryPipeline::addPipe(Processors pipe) +{ + checkInitialized(); + concatDelayedStream(); + + if (pipe.empty()) + throw Exception("Can't add empty processors list to QueryPipeline.", ErrorCodes::LOGICAL_ERROR); + + auto & first = pipe.front(); + auto & last = pipe.back(); + + auto num_inputs = first->getInputs().size(); + + if (num_inputs != streams.size()) + throw Exception("Can't add processors to QueryPipeline because first processor has " + toString(num_inputs) + + " input ports, but QueryPipeline has " + toString(streams.size()) + " streams.", + ErrorCodes::LOGICAL_ERROR); + + auto stream = streams.begin(); + for (auto & input : first->getInputs()) + connect(**(stream++), input); + + Block header; + streams.clear(); + streams.reserve(last->getOutputs().size()); + for (auto & output : last->getOutputs()) + { + streams.emplace_back(&output); + if (header) + assertBlocksHaveEqualStructure(header, output.getHeader(), "QueryPipeline"); + else + header = output.getHeader(); + } + + processors.insert(processors.end(), pipe.begin(), pipe.end()); + current_header = std::move(header); +} + +void QueryPipeline::addDelayedStream(ProcessorPtr source) +{ + checkInitialized(); + + if (delayed_stream_port) + throw Exception("QueryPipeline already has stream with non joined data.", ErrorCodes::LOGICAL_ERROR); + + checkSource(source, false); + assertBlocksHaveEqualStructure(current_header, source->getOutputs().front().getHeader(), "QueryPipeline"); + + delayed_stream_port = &source->getOutputs().front(); + processors.emplace_back(std::move(source)); +} + +void QueryPipeline::concatDelayedStream() +{ + if (!delayed_stream_port) + return; + + auto resize = std::make_shared(current_header, getNumMainStreams(), 1); + auto stream = streams.begin(); + for (auto & input : resize->getInputs()) + connect(**(stream++), input); + + auto concat = std::make_shared(current_header, 2); + connect(resize->getOutputs().front(), concat->getInputs().front()); + connect(*delayed_stream_port, concat->getInputs().back()); + + streams = { &concat->getOutputs().front() }; + processors.emplace_back(std::move(resize)); + processors.emplace_back(std::move(concat)); + + delayed_stream_port = nullptr; +} + +void QueryPipeline::resize(size_t num_streams) +{ + checkInitialized(); + concatDelayedStream(); + + if (num_streams == getNumStreams()) + return; + + has_resize = true; + + auto resize = std::make_shared(current_header, getNumStreams(), num_streams); + auto stream = streams.begin(); + for (auto & input : resize->getInputs()) + connect(**(stream++), input); + + streams.clear(); + streams.reserve(num_streams); + for (auto & output : resize->getOutputs()) + streams.emplace_back(&output); + + processors.emplace_back(std::move(resize)); +} + +void QueryPipeline::addTotalsHavingTransform(ProcessorPtr transform) +{ + checkInitialized(); + + if (!typeid_cast(transform.get())) + throw Exception("TotalsHavingTransform expected for QueryPipeline::addTotalsHavingTransform.", + ErrorCodes::LOGICAL_ERROR); + + if (totals_having_port) + throw Exception("Totals having transform was already added to pipeline.", ErrorCodes::LOGICAL_ERROR); + + resize(1); + + connect(*streams.front(), transform->getInputs().front()); + + auto & outputs = transform->getOutputs(); + + streams = { &outputs.front() }; + totals_having_port = &outputs.back(); + current_header = outputs.front().getHeader(); + processors.emplace_back(std::move(transform)); +} + +void QueryPipeline::addDefaultTotals() +{ + checkInitialized(); + + if (totals_having_port) + throw Exception("Totals having transform was already added to pipeline.", ErrorCodes::LOGICAL_ERROR); + + Columns columns; + columns.reserve(current_header.columns()); + + for (size_t i = 0; i < current_header.columns(); ++i) + { + auto column = current_header.getByPosition(i).type->createColumn(); + column->insertDefault(); + columns.emplace_back(std::move(column)); + } + + auto source = std::make_shared(current_header, Chunk(std::move(columns), 1)); + totals_having_port = &source->getPort(); + processors.emplace_back(source); +} + +void QueryPipeline::addTotals(ProcessorPtr source) +{ + checkInitialized(); + + if (totals_having_port) + throw Exception("Totals having transform was already added to pipeline.", ErrorCodes::LOGICAL_ERROR); + + checkSource(source, false); + assertBlocksHaveEqualStructure(current_header, source->getOutputs().front().getHeader(), "QueryPipeline"); + + totals_having_port = &source->getOutputs().front(); + processors.emplace_back(source); +} + +void QueryPipeline::dropTotalsIfHas() +{ + if (totals_having_port) + { + auto null_sink = std::make_shared(totals_having_port->getHeader()); + connect(*totals_having_port, null_sink->getPort()); + processors.emplace_back(std::move(null_sink)); + totals_having_port = nullptr; + } +} + +void QueryPipeline::addExtremesTransform(ProcessorPtr transform) +{ + checkInitialized(); + + if (!typeid_cast(transform.get())) + throw Exception("ExtremesTransform expected for QueryPipeline::addExtremesTransform.", + ErrorCodes::LOGICAL_ERROR); + + if (extremes_port) + throw Exception("Extremes transform was already added to pipeline.", ErrorCodes::LOGICAL_ERROR); + + if (getNumStreams() != 1) + throw Exception("Cant't add Extremes transform because pipeline is expected to have single stream, " + "but it has " + toString(getNumStreams()) + " streams.", ErrorCodes::LOGICAL_ERROR); + + connect(*streams.front(), transform->getInputs().front()); + + auto & outputs = transform->getOutputs(); + + streams = { &outputs.front() }; + extremes_port = &outputs.back(); + current_header = outputs.front().getHeader(); + processors.emplace_back(std::move(transform)); +} + +void QueryPipeline::addCreatingSetsTransform(ProcessorPtr transform) +{ + checkInitialized(); + + if (!typeid_cast(transform.get())) + throw Exception("CreatingSetsTransform expected for QueryPipeline::addExtremesTransform.", + ErrorCodes::LOGICAL_ERROR); + + resize(1); + + auto concat = std::make_shared(current_header, 2); + connect(transform->getOutputs().front(), concat->getInputs().front()); + connect(*streams.back(), concat->getInputs().back()); + + streams = { &concat->getOutputs().front() }; + processors.emplace_back(std::move(transform)); + processors.emplace_back(std::move(concat)); +} + +void QueryPipeline::setOutput(ProcessorPtr output) +{ + checkInitialized(); + + auto * format = dynamic_cast(output.get()); + + if (!format) + throw Exception("IOutputFormat processor expected for QueryPipeline::setOutput.", ErrorCodes::LOGICAL_ERROR); + + if (output_format) + throw Exception("QueryPipeline already has output.", ErrorCodes::LOGICAL_ERROR); + + output_format = format; + + resize(1); + + auto & main = format->getPort(IOutputFormat::PortKind::Main); + auto & totals = format->getPort(IOutputFormat::PortKind::Totals); + auto & extremes = format->getPort(IOutputFormat::PortKind::Extremes); + + if (!totals_having_port) + { + auto null_source = std::make_shared(totals.getHeader()); + totals_having_port = &null_source->getPort(); + processors.emplace_back(std::move(null_source)); + } + + if (!extremes_port) + { + auto null_source = std::make_shared(extremes.getHeader()); + extremes_port = &null_source->getPort(); + processors.emplace_back(std::move(null_source)); + } + + processors.emplace_back(std::move(output)); + + connect(*streams.front(), main); + connect(*totals_having_port, totals); + connect(*extremes_port, extremes); +} + +void QueryPipeline::unitePipelines( + std::vector && pipelines, const Block & common_header, const Context & context) +{ + checkInitialized(); + concatDelayedStream(); + + addSimpleTransform([&](const Block & header) + { + return std::make_shared( + header, common_header, ConvertingTransform::MatchColumnsMode::Position, context); + }); + + std::vector extremes; + + for (auto & pipeline : pipelines) + { + pipeline.checkInitialized(); + pipeline.concatDelayedStream(); + + pipeline.addSimpleTransform([&](const Block & header) + { + return std::make_shared( + header, common_header, ConvertingTransform::MatchColumnsMode::Position, context); + }); + + if (pipeline.extremes_port) + { + auto converting = std::make_shared( + pipeline.current_header, common_header, ConvertingTransform::MatchColumnsMode::Position, context); + + connect(*pipeline.extremes_port, converting->getInputPort()); + extremes.push_back(&converting->getOutputPort()); + processors.push_back(std::move(converting)); + } + + /// Take totals only from first port. + if (pipeline.totals_having_port) + { + if (!totals_having_port) + { + auto converting = std::make_shared( + pipeline.current_header, common_header, ConvertingTransform::MatchColumnsMode::Position, context); + + connect(*pipeline.totals_having_port, converting->getInputPort()); + totals_having_port = &converting->getOutputPort(); + processors.push_back(std::move(converting)); + } + else + pipeline.dropTotalsIfHas(); + } + + processors.insert(processors.end(), pipeline.processors.begin(), pipeline.processors.end()); + streams.insert(streams.end(), pipeline.streams.begin(), pipeline.streams.end()); + } + + if (!extremes.empty()) + { + size_t num_inputs = extremes.size() + (extremes_port ? 1u : 0u); + + if (num_inputs == 1) + extremes_port = extremes.front(); + else + { + /// Add extra processor for extremes. + auto resize = std::make_shared(current_header, num_inputs, 1); + auto input = resize->getInputs().begin(); + + if (extremes_port) + connect(*extremes_port, *(input++)); + + for (auto & output : extremes) + connect(*output, *(input++)); + + auto transform = std::make_shared(current_header); + extremes_port = &transform->getOutputPort(); + + connect(resize->getOutputs().front(), transform->getInputPort()); + processors.emplace_back(std::move(transform)); + } + } +} + +void QueryPipeline::setProgressCallback(const ProgressCallback & callback) +{ + for (auto & processor : processors) + { + if (auto * source = typeid_cast(processor.get())) + source->getStream().setProgressCallback(callback); + + if (auto * source = typeid_cast(processor.get())) + source->setProgressCallback(callback); + } +} + +void QueryPipeline::setProcessListElement(QueryStatus * elem) +{ + for (auto & processor : processors) + { + if (auto * source = typeid_cast(processor.get())) + source->getStream().setProcessListElement(elem); + + if (auto * source = typeid_cast(processor.get())) + source->setProcessListElement(elem); + } +} + +void QueryPipeline::finalize() +{ + checkInitialized(); + + if (!output_format) + throw Exception("Cannot finalize pipeline because it doesn't have output.", ErrorCodes::LOGICAL_ERROR); + + calcRowsBeforeLimit(); +} + +void QueryPipeline::calcRowsBeforeLimit() +{ + /// TODO get from Remote + + UInt64 rows_before_limit_at_least = 0; + UInt64 rows_before_limit = 0; + + bool has_limit = false; + bool has_partial_sorting = false; + + std::unordered_set visited; + + struct QueuedEntry + { + IProcessor * processor; + bool visited_limit; + }; + + std::queue queue; + + queue.push({ output_format, false }); + visited.emplace(output_format); + + while (!queue.empty()) + { + auto processor = queue.front().processor; + auto visited_limit = queue.front().visited_limit; + queue.pop(); + + if (!visited_limit) + { + if (auto * limit = typeid_cast(processor)) + { + has_limit = visited_limit = true; + rows_before_limit_at_least += limit->getRowsBeforeLimitAtLeast(); + } + + if (auto * source = typeid_cast(processor)) + { + auto & info = source->getStream().getProfileInfo(); + if (info.hasAppliedLimit()) + { + has_limit = visited_limit = true; + rows_before_limit_at_least += info.getRowsBeforeLimit(); + } + } + } + + if (auto * sorting = typeid_cast(processor)) + { + has_partial_sorting = true; + rows_before_limit += sorting->getNumReadRows(); + + /// Don't go to children. Take rows_before_limit from last PartialSortingTransform. + /// continue; + } + + /// Skip totals and extremes port for output format. + if (auto * format = dynamic_cast(processor)) + { + auto * child_processor = &format->getPort(IOutputFormat::PortKind::Main).getOutputPort().getProcessor(); + if (visited.emplace(child_processor).second) + queue.push({ child_processor, visited_limit }); + + continue; + } + + for (auto & child_port : processor->getInputs()) + { + auto * child_processor = &child_port.getOutputPort().getProcessor(); + if (visited.emplace(child_processor).second) + queue.push({ child_processor, visited_limit }); + } + } + + /// Get num read rows from PartialSortingTransform if have it. + if (has_limit) + output_format->setRowsBeforeLimit(has_partial_sorting ? rows_before_limit : rows_before_limit_at_least); +} + +PipelineExecutorPtr QueryPipeline::execute() +{ + checkInitialized(); + + if (!output_format) + throw Exception("Cannot execute pipeline because it doesn't have output.", ErrorCodes::LOGICAL_ERROR); + + return std::make_shared(processors); +} + +} diff --git a/dbms/src/Processors/QueryPipeline.h b/dbms/src/Processors/QueryPipeline.h new file mode 100644 index 00000000000..e932360971a --- /dev/null +++ b/dbms/src/Processors/QueryPipeline.h @@ -0,0 +1,119 @@ +#pragma once +#include +#include + +#include +#include + + +namespace DB +{ + +class TableStructureReadLock; +using TableStructureReadLockPtr = std::shared_ptr; +using TableStructureReadLocks = std::vector; + +class Context; + +class IOutputFormat; + +class QueryPipeline +{ +public: + QueryPipeline() = default; + + /// Each source must have single output port and no inputs. All outputs must have same header. + void init(Processors sources); + bool initialized() { return !processors.empty(); } + + enum class StreamType + { + Main = 0, + Totals, + Extremes, + }; + + using ProcessorGetter = std::function; + using ProcessorGetterWithStreamKind = std::function; + + void addSimpleTransform(const ProcessorGetter & getter); + void addSimpleTransform(const ProcessorGetterWithStreamKind & getter); + void addPipe(Processors pipe); + void addTotalsHavingTransform(ProcessorPtr transform); + void addExtremesTransform(ProcessorPtr transform); + void addCreatingSetsTransform(ProcessorPtr transform); + void setOutput(ProcessorPtr output); + + /// Add totals which returns one chunk with single row with defaults. + void addDefaultTotals(); + + /// Add already calculated totals. + void addTotals(ProcessorPtr source); + + void dropTotalsIfHas(); + + /// Will read from this stream after all data was read from other streams. + void addDelayedStream(ProcessorPtr source); + bool hasDelayedStream() const { return delayed_stream_port; } + /// Check if resize transform was used. (In that case another distinct transform will be added). + bool hasMixedStreams() const { return has_resize || hasMoreThanOneStream(); } + + void resize(size_t num_streams); + + void unitePipelines(std::vector && pipelines, const Block & common_header, const Context & context); + + PipelineExecutorPtr execute(); + + size_t getNumStreams() const { return streams.size() + (hasDelayedStream() ? 1 : 0); } + size_t getNumMainStreams() const { return streams.size(); } + + bool hasMoreThanOneStream() const { return getNumStreams() > 1; } + bool hasTotals() const { return totals_having_port != nullptr; } + + const Block & getHeader() const { return current_header; } + + void addTableLock(const TableStructureReadLockPtr & lock) { table_locks.push_back(lock); } + + /// For compatibility with IBlockInputStream. + void setProgressCallback(const ProgressCallback & callback); + void setProcessListElement(QueryStatus * elem); + + /// Call after execution. + void finalize(); + +private: + + /// All added processors. + Processors processors; + + /// Port for each independent "stream". + std::vector streams; + + /// Special ports for extremes and totals having. + OutputPort * totals_having_port = nullptr; + OutputPort * extremes_port = nullptr; + + /// Special port for delayed stream. + OutputPort * delayed_stream_port = nullptr; + + /// If resize processor was added to pipeline. + bool has_resize = false; + + /// Common header for each stream. + Block current_header; + + TableStructureReadLocks table_locks; + + IOutputFormat * output_format = nullptr; + + void checkInitialized(); + void checkSource(const ProcessorPtr & source, bool can_have_totals); + void concatDelayedStream(); + + template + void addSimpleTransformImpl(const TProcessorGetter & getter); + + void calcRowsBeforeLimit(); +}; + +} diff --git a/dbms/src/Processors/QueueBuffer.h b/dbms/src/Processors/QueueBuffer.h new file mode 100644 index 00000000000..d81f7e779a3 --- /dev/null +++ b/dbms/src/Processors/QueueBuffer.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + + +namespace DB +{ + +class QueueBuffer : public IAccumulatingTransform +{ +private: + std::queue chunks; +public: + String getName() const override { return "QueueBuffer"; } + + QueueBuffer(Block header) + : IAccumulatingTransform(header, header) + { + } + + void consume(Chunk block) override + { + chunks.push(std::move(block)); + } + + Chunk generate() override + { + if (chunks.empty()) + return {}; + + auto res = std::move(chunks.front()); + chunks.pop(); + return res; + } +}; + +} diff --git a/dbms/src/Processors/ResizeProcessor.cpp b/dbms/src/Processors/ResizeProcessor.cpp new file mode 100644 index 00000000000..b3cb3a1735d --- /dev/null +++ b/dbms/src/Processors/ResizeProcessor.cpp @@ -0,0 +1,157 @@ +#include + + +namespace DB +{ + +ResizeProcessor::Status ResizeProcessor::prepare() +{ + bool is_first_output = true; + auto output_end = current_output; + + bool all_outs_full_or_unneeded = true; + bool all_outs_finished = true; + + bool is_first_input = true; + auto input_end = current_input; + + bool all_inputs_finished = true; + + auto is_end_input = [&]() { return !is_first_input && current_input == input_end; }; + auto is_end_output = [&]() { return !is_first_output && current_output == output_end; }; + + auto inc_current_input = [&]() + { + is_first_input = false; + ++current_input; + + if (current_input == inputs.end()) + current_input = inputs.begin(); + }; + + auto inc_current_output = [&]() + { + is_first_output = false; + ++current_output; + + if (current_output == outputs.end()) + current_output = outputs.begin(); + }; + + /// Find next output where can push. + auto get_next_out = [&, this]() -> OutputPorts::iterator + { + while (!is_end_output()) + { + if (!current_output->isFinished()) + { + all_outs_finished = false; + + if (current_output->canPush()) + { + all_outs_full_or_unneeded = false; + auto res_output = current_output; + inc_current_output(); + return res_output; + } + } + + inc_current_output(); + } + + return outputs.end(); + }; + + /// Find next input from where can pull. + auto get_next_input = [&, this]() -> InputPorts::iterator + { + while (!is_end_input()) + { + if (!current_input->isFinished()) + { + all_inputs_finished = false; + + current_input->setNeeded(); + if (current_input->hasData()) + { + auto res_input = current_input; + inc_current_input(); + return res_input; + } + } + + inc_current_input(); + } + + return inputs.end(); + }; + + auto get_status_if_no_outputs = [&]() -> Status + { + if (all_outs_finished) + { + for (auto & in : inputs) + in.close(); + + return Status::Finished; + } + + if (all_outs_full_or_unneeded) + { + for (auto & in : inputs) + in.setNotNeeded(); + + return Status::PortFull; + } + + /// Now, we pushed to output, and it must be full. + return Status::PortFull; + }; + + auto get_status_if_no_inputs = [&]() -> Status + { + if (all_inputs_finished) + { + for (auto & out : outputs) + out.finish(); + + return Status::Finished; + } + + return Status::NeedData; + }; + + /// Set all inputs needed in order to evenly process them. + /// Otherwise, in case num_outputs < num_inputs and chunks are consumed faster than produced, + /// some inputs can be skipped. +// auto set_all_unprocessed_inputs_needed = [&]() +// { +// for (; cur_input != inputs.end(); ++cur_input) +// if (!cur_input->isFinished()) +// cur_input->setNeeded(); +// }; + + while (!is_end_input() && !is_end_output()) + { + auto output = get_next_out(); + auto input = get_next_input(); + + if (output == outputs.end()) + return get_status_if_no_outputs(); + + + if (input == inputs.end()) + return get_status_if_no_inputs(); + + output->push(input->pull()); + } + + if (is_end_input()) + return get_status_if_no_outputs(); + + /// cur_input == inputs_end() + return get_status_if_no_inputs(); +} + +} + diff --git a/dbms/src/Processors/ResizeProcessor.h b/dbms/src/Processors/ResizeProcessor.h new file mode 100644 index 00000000000..67574c384a1 --- /dev/null +++ b/dbms/src/Processors/ResizeProcessor.h @@ -0,0 +1,40 @@ +#pragma once + +#include + + +namespace DB +{ + +/** Has arbitary non zero number of inputs and arbitary non zero number of outputs. + * All of them have the same structure. + * + * Pulls data from arbitary input (whenever it is ready) and pushes it to arbitary output (whenever is is not full). + * Doesn't do any heavy calculations. + * Doesn't preserve an order of data. + * + * Examples: + * - union data from multiple inputs to single output - to serialize data that was processed in parallel. + * - split data from single input to multiple outputs - to allow further parallel processing. + */ +class ResizeProcessor : public IProcessor +{ +public: + /// TODO Check that there is non zero number of inputs and outputs. + ResizeProcessor(const Block & header, size_t num_inputs, size_t num_outputs) + : IProcessor(InputPorts(num_inputs, header), OutputPorts(num_outputs, header)) + , current_input(inputs.begin()) + , current_output(outputs.begin()) + { + } + + String getName() const override { return "Resize"; } + + Status prepare() override; + +private: + InputPorts::iterator current_input; + OutputPorts::iterator current_output; +}; + +} diff --git a/dbms/src/Processors/Sources/NullSource.h b/dbms/src/Processors/Sources/NullSource.h new file mode 100644 index 00000000000..d1f0ec5e6ca --- /dev/null +++ b/dbms/src/Processors/Sources/NullSource.h @@ -0,0 +1,18 @@ +#pragma once +#include + + +namespace DB +{ + +class NullSource : public ISource +{ +public: + explicit NullSource(Block header) : ISource(std::move(header)) {} + String getName() const override { return "NullSource"; } + +protected: + Chunk generate() override { return Chunk(); } +}; + +} diff --git a/dbms/src/Processors/Sources/SourceFromInputStream.cpp b/dbms/src/Processors/Sources/SourceFromInputStream.cpp new file mode 100644 index 00000000000..d9d74a5cde6 --- /dev/null +++ b/dbms/src/Processors/Sources/SourceFromInputStream.cpp @@ -0,0 +1,142 @@ +#include +#include +#include +#include + +namespace DB +{ + +SourceFromInputStream::SourceFromInputStream(BlockInputStreamPtr stream_, bool force_add_aggregating_info) + : ISource(stream_->getHeader()) + , force_add_aggregating_info(force_add_aggregating_info) + , stream(std::move(stream_)) +{ + auto & sample = getPort().getHeader(); + for (auto & type : sample.getDataTypes()) + if (typeid_cast(type.get())) + has_aggregate_functions = true; +} + +void SourceFromInputStream::addTotalsPort() +{ + if (has_totals_port) + throw Exception("Totals port was already added for SourceFromInputStream.", ErrorCodes::LOGICAL_ERROR); + + outputs.emplace_back(outputs.front().getHeader(), this); + has_totals_port = true; +} + +IProcessor::Status SourceFromInputStream::prepare() +{ + auto status = ISource::prepare(); + + if (status == Status::Finished) + { + is_generating_finished = true; + + /// Read postfix and get totals if needed. + if (!is_stream_finished) + return Status::Ready; + + if (has_totals_port) + { + auto & totals_out = outputs.back(); + + if (totals_out.isFinished()) + return Status::Finished; + + if (has_totals) + { + if (!totals_out.canPush()) + return Status::PortFull; + + totals_out.push(std::move(totals)); + has_totals = false; + } + + totals_out.finish(); + } + } + + return status; +} + +void SourceFromInputStream::work() +{ + if (!is_generating_finished) + { + try + { + ISource::work(); + } + catch (...) + { + /// Won't read suffix in case of exception. + is_stream_finished = true; + throw; + } + + return; + } + + if (is_stream_finished) + return; + + /// Don't cancel for RemoteBlockInputStream (otherwise readSuffix can stack) + if (!typeid_cast(stream.get())) + stream->cancel(false); + + stream->readSuffix(); + + if (auto totals_block = stream->getTotals()) + { + totals.setColumns(totals_block.getColumns(), 1); + has_totals = true; + } + + is_stream_finished = true; +} + +Chunk SourceFromInputStream::generate() +{ + if (is_stream_finished) + return {}; + + if (!is_stream_started) + { + stream->readPrefix(); + is_stream_started = true; + } + + auto block = stream->read(); + if (!block) + { + stream->readSuffix(); + + if (auto totals_block = stream->getTotals()) + { + totals.setColumns(totals_block.getColumns(), 1); + has_totals = true; + } + + is_stream_finished = true; + return {}; + } + + assertBlocksHaveEqualStructure(getPort().getHeader(), block, "SourceFromInputStream"); + + UInt64 num_rows = block.rows(); + Chunk chunk(block.getColumns(), num_rows); + + if (force_add_aggregating_info || has_aggregate_functions) + { + auto info = std::make_shared(); + info->bucket_num = block.info.bucket_num; + info->is_overflows = block.info.is_overflows; + chunk.setChunkInfo(std::move(info)); + } + + return chunk; +} + +} diff --git a/dbms/src/Processors/Sources/SourceFromInputStream.h b/dbms/src/Processors/Sources/SourceFromInputStream.h new file mode 100644 index 00000000000..46e0b3fb04b --- /dev/null +++ b/dbms/src/Processors/Sources/SourceFromInputStream.h @@ -0,0 +1,39 @@ +#pragma once +#include + +namespace DB +{ + +class IBlockInputStream; +using BlockInputStreamPtr = std::shared_ptr; + +class SourceFromInputStream : public ISource +{ +public: + explicit SourceFromInputStream(BlockInputStreamPtr stream_, bool force_add_aggregating_info = false); + String getName() const override { return "SourceFromInputStream"; } + + Status prepare() override; + void work() override; + + Chunk generate() override; + + IBlockInputStream & getStream() { return *stream; } + + void addTotalsPort(); + +private: + bool has_aggregate_functions = false; + bool force_add_aggregating_info; + BlockInputStreamPtr stream; + + Chunk totals; + bool has_totals_port = false; + bool has_totals = false; + + bool is_generating_finished = false; + bool is_stream_finished = false; + bool is_stream_started = false; +}; + +} diff --git a/dbms/src/Processors/Sources/SourceFromSingleChunk.h b/dbms/src/Processors/Sources/SourceFromSingleChunk.h new file mode 100644 index 00000000000..4384597e28b --- /dev/null +++ b/dbms/src/Processors/Sources/SourceFromSingleChunk.h @@ -0,0 +1,21 @@ +#pragma once +#include + + +namespace DB +{ + +class SourceFromSingleChunk : public ISource +{ +public: + explicit SourceFromSingleChunk(Block header, Chunk chunk_) : ISource(std::move(header)), chunk(std::move(chunk_)) {} + String getName() const override { return "SourceFromSingleChunk"; } + +protected: + Chunk generate() override { return std::move(chunk); } + +private: + Chunk chunk; +}; + +} diff --git a/dbms/src/Processors/Transforms/AggregatingTransform.cpp b/dbms/src/Processors/Transforms/AggregatingTransform.cpp new file mode 100644 index 00000000000..5993584f5c9 --- /dev/null +++ b/dbms/src/Processors/Transforms/AggregatingTransform.cpp @@ -0,0 +1,299 @@ +#include + +#include +#include +#include +#include +#include + +namespace ProfileEvents +{ + extern const Event ExternalAggregationMerge; +} + +namespace DB +{ + +namespace +{ + class SourceFromNativeStream : public ISource + { + public: + SourceFromNativeStream(const Block & header, const std::string & path) + : ISource(header), file_in(path), compressed_in(file_in) + , block_in(std::make_shared(compressed_in, ClickHouseRevision::get())) + { + block_in->readPrefix(); + } + + String getName() const override { return "SourceFromNativeStream"; } + + Chunk generate() override + { + if (!block_in) + return {}; + + auto block = block_in->read(); + if (!block) + { + block_in->readSuffix(); + block_in.reset(); + return {}; + } + + auto info = std::make_shared(); + info->bucket_num = block.info.bucket_num; + info->is_overflows = block.info.is_overflows; + + UInt64 num_rows = block.rows(); + Chunk chunk(block.getColumns(), num_rows); + chunk.setChunkInfo(std::move(info)); + + return chunk; + } + + private: + ReadBufferFromFile file_in; + CompressedReadBuffer compressed_in; + BlockInputStreamPtr block_in; + }; + + class ConvertingAggregatedToBlocksTransform : public ISource + { + public: + ConvertingAggregatedToBlocksTransform(Block header, AggregatingTransformParamsPtr params_, BlockInputStreamPtr stream) + : ISource(std::move(header)), params(std::move(params_)), stream(std::move(stream)) {} + + String getName() const override { return "ConvertingAggregatedToBlocksTransform"; } + + protected: + Chunk generate() override + { + auto block = stream->read(); + if (!block) + return {}; + + auto info = std::make_shared(); + info->bucket_num = block.info.bucket_num; + info->is_overflows = block.info.is_overflows; + + UInt64 num_rows = block.rows(); + Chunk chunk(block.getColumns(), num_rows); + chunk.setChunkInfo(std::move(info)); + + return chunk; + } + + private: + /// Store params because aggregator must be destroyed after stream. Order is important. + AggregatingTransformParamsPtr params; + BlockInputStreamPtr stream; + }; +} + +AggregatingTransform::AggregatingTransform(Block header, AggregatingTransformParamsPtr params_) + : AggregatingTransform(std::move(header), std::move(params_) + , std::make_unique(1), 0, 1, 1) +{ +} + +AggregatingTransform::AggregatingTransform( + Block header, AggregatingTransformParamsPtr params_, ManyAggregatedDataPtr many_data_, + size_t current_variant, size_t temporary_data_merge_threads, size_t max_threads) + : IProcessor({std::move(header)}, {params_->getHeader()}), params(std::move(params_)) + , key(params->params.keys_size) + , key_columns(params->params.keys_size) + , aggregate_columns(params->params.aggregates_size) + , many_data(std::move(many_data_)) + , variants(*many_data->variants[current_variant]) + , max_threads(std::min(many_data->variants.size(), max_threads)) + , temporary_data_merge_threads(temporary_data_merge_threads) +{ +} + +AggregatingTransform::~AggregatingTransform() = default; + +IProcessor::Status AggregatingTransform::prepare() +{ + auto & output = outputs.front(); + /// Last output is current. All other outputs should already be closed. + auto & input = inputs.back(); + + /// Check can output. + if (output.isFinished()) + { + input.close(); + return Status::Finished; + } + + if (!output.canPush()) + { + input.setNotNeeded(); + return Status::PortFull; + } + + /// Finish data processing, prepare to generating. + if (is_consume_finished && !is_generate_initialized) + return Status::Ready; + + if (is_generate_initialized && !is_pipeline_created && !processors.empty()) + return Status::ExpandPipeline; + + /// Only possible while consuming. + if (read_current_chunk) + return Status::Ready; + + /// Get chunk from input. + if (input.isFinished()) + { + if (is_consume_finished) + { + output.finish(); + return Status::Finished; + } + else + { + /// Finish data processing and create another pipe. + is_consume_finished = true; + return Status::Ready; + } + } + + input.setNeeded(); + if (!input.hasData()) + return Status::NeedData; + + current_chunk = input.pull(); + read_current_chunk = true; + + if (is_consume_finished) + { + output.push(std::move(current_chunk)); + read_current_chunk = false; + return Status::PortFull; + } + + return Status::Ready; +} + +void AggregatingTransform::work() +{ + if (is_consume_finished) + initGenerate(); + else + { + consume(std::move(current_chunk)); + read_current_chunk = false; + } +} + +Processors AggregatingTransform::expandPipeline() +{ + auto & out = processors.back()->getOutputs().front(); + inputs.emplace_back(out.getHeader(), this); + connect(out, inputs.back()); + is_pipeline_created = true; + return std::move(processors); +} + +void AggregatingTransform::consume(Chunk chunk) +{ + if (chunk.getNumRows() == 0 && params->params.empty_result_for_aggregation_by_empty_set) + return; + + if (!is_consume_started) + { + LOG_TRACE(log, "Aggregating"); + is_consume_started = true; + } + + src_rows += chunk.getNumRows(); + src_bytes += chunk.bytes(); + + auto block = getInputs().front().getHeader().cloneWithColumns(chunk.detachColumns()); + + if (!params->aggregator.executeOnBlock(block, variants, key_columns, aggregate_columns, key, no_more_keys)) + is_consume_finished = true; +} + +void AggregatingTransform::initGenerate() +{ + if (is_generate_initialized) + return; + + is_generate_initialized = true; + + /// If there was no data, and we aggregate without keys, and we must return single row with the result of empty aggregation. + /// To do this, we pass a block with zero rows to aggregate. + if (variants.empty() && params->params.keys_size == 0 && !params->params.empty_result_for_aggregation_by_empty_set) + params->aggregator.executeOnBlock(getInputs().front().getHeader(), variants, key_columns, aggregate_columns, key, no_more_keys); + + double elapsed_seconds = watch.elapsedSeconds(); + size_t rows = variants.sizeWithoutOverflowRow(); + LOG_TRACE(log, std::fixed << std::setprecision(3) + << "Aggregated. " << src_rows << " to " << rows << " rows (from " << src_bytes / 1048576.0 << " MiB)" + << " in " << elapsed_seconds << " sec." + << " (" << src_rows / elapsed_seconds << " rows/sec., " << src_bytes / elapsed_seconds / 1048576.0 << " MiB/sec.)"); + + if (params->aggregator.hasTemporaryFiles()) + { + if (variants.isConvertibleToTwoLevel()) + variants.convertToTwoLevel(); + + /// Flush data in the RAM to disk also. It's easier than merging on-disk and RAM data. + if (variants.size()) + params->aggregator.writeToTemporaryFile(variants); + } + + if (many_data->num_finished.fetch_add(1) + 1 < many_data->variants.size()) + return; + + if (!params->aggregator.hasTemporaryFiles()) + { + auto stream = params->aggregator.mergeAndConvertToBlocks(many_data->variants, params->final, max_threads); + processors.emplace_back(std::make_shared(stream->getHeader(), params, std::move(stream))); + } + else + { + /// If there are temporary files with partially-aggregated data on the disk, + /// then read and merge them, spending the minimum amount of memory. + + ProfileEvents::increment(ProfileEvents::ExternalAggregationMerge); + + if (many_data->variants.size() > 1) + { + /// It may happen that some data has not yet been flushed, + /// because at the time thread has finished, no data has been flushed to disk, and then some were. + for (auto & cur_variants : many_data->variants) + { + if (cur_variants->isConvertibleToTwoLevel()) + cur_variants->convertToTwoLevel(); + + if (cur_variants->size()) + params->aggregator.writeToTemporaryFile(*cur_variants); + } + } + + auto header = params->aggregator.getHeader(false); + + const auto & files = params->aggregator.getTemporaryFiles(); + BlockInputStreams input_streams; + for (const auto & file : files.files) + processors.emplace_back(std::make_unique(header, file->path())); + + LOG_TRACE(log, "Will merge " << files.files.size() << " temporary files of size " + << (files.sum_size_compressed / 1048576.0) << " MiB compressed, " + << (files.sum_size_uncompressed / 1048576.0) << " MiB uncompressed."); + + auto pipe = createMergingAggregatedMemoryEfficientPipe( + header, params, files.files.size(), temporary_data_merge_threads); + + auto input = pipe.front()->getInputs().begin(); + for (auto & processor : processors) + connect(processor->getOutputs().front(), *(input++)); + + processors.insert(processors.end(), pipe.begin(), pipe.end()); + } +} + +} diff --git a/dbms/src/Processors/Transforms/AggregatingTransform.h b/dbms/src/Processors/Transforms/AggregatingTransform.h new file mode 100644 index 00000000000..64ba10e1801 --- /dev/null +++ b/dbms/src/Processors/Transforms/AggregatingTransform.h @@ -0,0 +1,102 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace DB +{ + +class AggregatedChunkInfo : public ChunkInfo +{ +public: + bool is_overflows = false; + Int32 bucket_num = -1; +}; + +class IBlockInputStream; +using BlockInputStreamPtr = std::shared_ptr; + +struct AggregatingTransformParams +{ + Aggregator::Params params; + Aggregator aggregator; + bool final; + + AggregatingTransformParams(const Aggregator::Params & params, bool final) + : params(params), aggregator(params), final(final) {} + + Block getHeader() const { return aggregator.getHeader(final); } +}; + +struct ManyAggregatedData +{ + ManyAggregatedDataVariants variants; + std::atomic num_finished = 0; + + explicit ManyAggregatedData(size_t num_threads = 0) : variants(num_threads) + { + for (auto & elem : variants) + elem = std::make_shared(); + } +}; + +using AggregatingTransformParamsPtr = std::shared_ptr; +using ManyAggregatedDataPtr = std::shared_ptr; + +class AggregatingTransform : public IProcessor +{ +public: + AggregatingTransform(Block header, AggregatingTransformParamsPtr params_); + + /// For Parallel aggregating. + AggregatingTransform(Block header, AggregatingTransformParamsPtr params_, + ManyAggregatedDataPtr many_data, size_t current_variant, + size_t temporary_data_merge_threads, size_t max_threads); + ~AggregatingTransform() override; + + String getName() const override { return "AggregatingTransform"; } + Status prepare() override; + void work() override; + Processors expandPipeline() override; + +protected: + void consume(Chunk chunk); + +private: + /// To read the data that was flushed into the temporary data file. + Processors processors; + + AggregatingTransformParamsPtr params; + Logger * log = &Logger::get("AggregatingTransform"); + + StringRefs key; + ColumnRawPtrs key_columns; + Aggregator::AggregateColumns aggregate_columns; + bool no_more_keys = false; + + ManyAggregatedDataPtr many_data; + AggregatedDataVariants & variants; + size_t max_threads = 1; + size_t temporary_data_merge_threads = 1; + + /// TODO: calculate time only for aggregation. + Stopwatch watch; + + UInt64 src_rows = 0; + UInt64 src_bytes = 0; + + bool is_generate_initialized = false; + bool is_consume_finished = false; + bool is_pipeline_created = false; + + Chunk current_chunk; + bool read_current_chunk = false; + + bool is_consume_started = false; + + void initGenerate(); +}; + +} diff --git a/dbms/src/Processors/Transforms/ConvertingTransform.cpp b/dbms/src/Processors/Transforms/ConvertingTransform.cpp new file mode 100644 index 00000000000..49dbb748591 --- /dev/null +++ b/dbms/src/Processors/Transforms/ConvertingTransform.cpp @@ -0,0 +1,127 @@ +#include + +#include +#include +#include +#include + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int THERE_IS_NO_COLUMN; + extern const int BLOCKS_HAVE_DIFFERENT_STRUCTURE; + extern const int NUMBER_OF_COLUMNS_DOESNT_MATCH; +} + +static ColumnPtr castColumnWithDiagnostic( + const ColumnWithTypeAndName & src_elem, + const ColumnWithTypeAndName & res_elem, + const Context & context) +{ + try + { + return castColumn(src_elem, res_elem.type, context); + } + catch (Exception & e) + { + e.addMessage("while converting source column " + backQuoteIfNeed(src_elem.name) + + " to destination column " + backQuoteIfNeed(res_elem.name)); + throw; + } +} + +ConvertingTransform::ConvertingTransform( + Block source_header, + Block result_header, + MatchColumnsMode mode, + const Context & context) + : ISimpleTransform(std::move(source_header), std::move(result_header), false) + , context(context) + , conversion(getOutputPort().getHeader().columns()) +{ + auto & source = getInputPort().getHeader(); + auto & result = getOutputPort().getHeader(); + + size_t num_input_columns = source.columns(); + size_t num_result_columns = result.columns(); + + if (mode == MatchColumnsMode::Position && num_input_columns != num_result_columns) + throw Exception("Number of columns doesn't match", ErrorCodes::NUMBER_OF_COLUMNS_DOESNT_MATCH); + + for (size_t result_col_num = 0; result_col_num < num_result_columns; ++result_col_num) + { + const auto & res_elem = result.getByPosition(result_col_num); + + switch (mode) + { + case MatchColumnsMode::Position: + conversion[result_col_num] = result_col_num; + break; + + case MatchColumnsMode::Name: + if (source.has(res_elem.name)) + conversion[result_col_num] = source.getPositionByName(res_elem.name); + else + throw Exception("Cannot find column " + backQuoteIfNeed(res_elem.name) + " in source stream", + ErrorCodes::THERE_IS_NO_COLUMN); + break; + } + + const auto & src_elem = source.getByPosition(conversion[result_col_num]); + + /// Check constants. + + if (auto * res_const = typeid_cast(res_elem.column.get())) + { + if (auto * src_const = typeid_cast(src_elem.column.get())) + { + if (res_const->getField() != src_const->getField()) + throw Exception("Cannot convert column " + backQuoteIfNeed(res_elem.name) + " because " + "it is constant but values of constants are different in source and result", + ErrorCodes::BLOCKS_HAVE_DIFFERENT_STRUCTURE); + } + else + throw Exception("Cannot convert column " + backQuoteIfNeed(res_elem.name) + " because " + "it is non constant in source stream but must be constant in result", + ErrorCodes::BLOCKS_HAVE_DIFFERENT_STRUCTURE); + } + + /// Check conversion by dry run CAST function. + + castColumnWithDiagnostic(src_elem, res_elem, context); + } +} + +void ConvertingTransform::transform(Chunk & chunk) +{ + auto & source = getInputPort().getHeader(); + auto & result = getOutputPort().getHeader(); + + auto num_rows = chunk.getNumRows(); + auto src_columns = chunk.detachColumns(); + + size_t num_res_columns = conversion.size(); + + Columns res_columns; + res_columns.reserve(num_res_columns); + + for (size_t res_pos = 0; res_pos < num_res_columns; ++res_pos) + { + auto src_elem = source.getByPosition(conversion[res_pos]); + src_elem.column = src_columns[conversion[res_pos]]; + auto res_elem = result.getByPosition(res_pos); + + ColumnPtr converted = castColumnWithDiagnostic(src_elem, res_elem, context); + + if (!isColumnConst(*res_elem.column)) + converted = converted->convertToFullColumnIfConst(); + + res_columns.emplace_back(std::move(converted)); + } + + chunk.setColumns(std::move(res_columns), num_rows); +} + +} diff --git a/dbms/src/Processors/Transforms/ConvertingTransform.h b/dbms/src/Processors/Transforms/ConvertingTransform.h new file mode 100644 index 00000000000..d6e6219316a --- /dev/null +++ b/dbms/src/Processors/Transforms/ConvertingTransform.h @@ -0,0 +1,49 @@ +#include +#include + +namespace DB +{ + +/** Convert one block structure to another: + * + * Leaves only necessary columns; + * + * Columns are searched in source first by name; + * and if there is no column with same name, then by position. + * + * Converting types of matching columns (with CAST function). + * + * Materializing columns which are const in source and non-const in result, + * throw if they are const in result and non const in source, + * or if they are const and have different values. + */ +class ConvertingTransform : public ISimpleTransform +{ +public: + enum class MatchColumnsMode + { + /// Require same number of columns in source and result. Match columns by corresponding positions, regardless to names. + Position, + /// Find columns in source by their names. Allow excessive columns in source. + Name, + }; + + ConvertingTransform( + Block source_header, + Block result_header, + MatchColumnsMode mode, + const Context & context); + + String getName() const override { return "Converting"; } + +protected: + void transform(Chunk & chunk) override; + +private: + const Context & context; + + /// How to construct result block. Position in source block, where to get each column. + ColumnNumbers conversion; +}; + +} diff --git a/dbms/src/Processors/Transforms/CreatingSetsTransform.cpp b/dbms/src/Processors/Transforms/CreatingSetsTransform.cpp new file mode 100644 index 00000000000..29bc4030b81 --- /dev/null +++ b/dbms/src/Processors/Transforms/CreatingSetsTransform.cpp @@ -0,0 +1,223 @@ +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int SET_SIZE_LIMIT_EXCEEDED; +} + + +CreatingSetsTransform::CreatingSetsTransform( + Block out_header, + const SubqueriesForSets & subqueries_for_sets_, + const SizeLimits & network_transfer_limits, + const Context & context) + : IProcessor({}, {std::move(out_header)}) + , subqueries_for_sets(subqueries_for_sets_) + , cur_subquery(subqueries_for_sets.begin()) + , network_transfer_limits(network_transfer_limits) + , context(context) +{ +} + +IProcessor::Status CreatingSetsTransform::prepare() +{ + auto & output = outputs.front(); + + if (finished) + { + output.finish(); + return Status::Finished; + } + + /// Check can output. + if (output.isFinished()) + return Status::Finished; + + if (!output.canPush()) + return Status::PortFull; + + return Status::Ready; +} + +void CreatingSetsTransform::startSubquery(SubqueryForSet & subquery) +{ + LOG_TRACE(log, (subquery.set ? "Creating set. " : "") + << (subquery.join ? "Creating join. " : "") + << (subquery.table ? "Filling temporary table. " : "")); + + elapsed_nanoseconds = 0; + + if (subquery.table) + table_out = subquery.table->write({}, context); + + done_with_set = !subquery.set; + done_with_join = !subquery.join; + done_with_table = !subquery.table; + + if (done_with_set && done_with_join && done_with_table) + throw Exception("Logical error: nothing to do with subquery", ErrorCodes::LOGICAL_ERROR); + + if (table_out) + table_out->writePrefix(); +} + +void CreatingSetsTransform::finishSubquery(SubqueryForSet & subquery) +{ + size_t head_rows = 0; + const BlockStreamProfileInfo & profile_info = subquery.source->getProfileInfo(); + + head_rows = profile_info.rows; + + if (subquery.join) + subquery.join->setTotals(subquery.source->getTotals()); + + if (head_rows != 0) + { + std::stringstream msg; + msg << std::fixed << std::setprecision(3); + msg << "Created. "; + + if (subquery.set) + msg << "Set with " << subquery.set->getTotalRowCount() << " entries from " << head_rows << " rows. "; + if (subquery.join) + msg << "Join with " << subquery.join->getTotalRowCount() << " entries from " << head_rows << " rows. "; + if (subquery.table) + msg << "Table with " << head_rows << " rows. "; + + msg << "In " << (static_cast(elapsed_nanoseconds) / 1000000000ULL) << " sec."; + LOG_DEBUG(log, msg.rdbuf()); + } + else + { + LOG_DEBUG(log, "Subquery has empty result."); + } +} + +void CreatingSetsTransform::init() +{ + is_initialized = true; + + for (auto & elem : subqueries_for_sets) + if (elem.second.source && elem.second.set) + elem.second.set->setHeader(elem.second.source->getHeader()); +} + +void CreatingSetsTransform::work() +{ + if (!is_initialized) + init(); + + Stopwatch watch; + + while (cur_subquery != subqueries_for_sets.end() && cur_subquery->second.source == nullptr) + ++cur_subquery; + + if (cur_subquery == subqueries_for_sets.end()) + { + finished = true; + return; + } + + SubqueryForSet & subquery = cur_subquery->second; + + if (!started_cur_subquery) + { + startSubquery(subquery); + started_cur_subquery = true; + } + + auto finishCurrentSubquery = [&]() + { + if (table_out) + table_out->writeSuffix(); + + watch.stop(); + elapsed_nanoseconds += watch.elapsedNanoseconds(); + + finishSubquery(subquery); + + ++cur_subquery; + started_cur_subquery = false; + + while (cur_subquery != subqueries_for_sets.end() && cur_subquery->second.source == nullptr) + ++cur_subquery; + + if (cur_subquery == subqueries_for_sets.end()) + finished = true; + }; + + auto block = subquery.source->read(); + if (!block) + { + finishCurrentSubquery(); + return; + } + + if (!done_with_set) + { + if (!subquery.set->insertFromBlock(block)) + done_with_set = true; + } + + if (!done_with_join) + { + subquery.renameColumns(block); + + if (subquery.joined_block_actions) + subquery.joined_block_actions->execute(block); + + if (!subquery.join->insertFromBlock(block)) + done_with_join = true; + } + + if (!done_with_table) + { + block = materializeBlock(block); + table_out->write(block); + + rows_to_transfer += block.rows(); + bytes_to_transfer += block.bytes(); + + if (!network_transfer_limits.check(rows_to_transfer, bytes_to_transfer, "IN/JOIN external table", + ErrorCodes::SET_SIZE_LIMIT_EXCEEDED)) + done_with_table = true; + } + + if (done_with_set && done_with_join && done_with_table) + { + subquery.source->cancel(false); + finishCurrentSubquery(); + } + else + elapsed_nanoseconds += watch.elapsedNanoseconds(); +} + +void CreatingSetsTransform::setProgressCallback(const ProgressCallback & callback) +{ + for (auto & elem : subqueries_for_sets) + if (elem.second.source) + elem.second.source->setProgressCallback(callback); +} + +void CreatingSetsTransform::setProcessListElement(QueryStatus * status) +{ + for (auto & elem : subqueries_for_sets) + if (elem.second.source) + elem.second.source->setProcessListElement(status); +} + +} diff --git a/dbms/src/Processors/Transforms/CreatingSetsTransform.h b/dbms/src/Processors/Transforms/CreatingSetsTransform.h new file mode 100644 index 00000000000..b5f7ea63748 --- /dev/null +++ b/dbms/src/Processors/Transforms/CreatingSetsTransform.h @@ -0,0 +1,63 @@ +#pragma once +#include +#include +#include + +namespace DB +{ + +struct Progress; +using ProgressCallback = std::function; + +/// This processor creates sets during execution. +/// Don't return any data. Sets are created when Finish status is returned. +/// In general, several work() methods need to be called to finish. +/// TODO: several independent processors can be created for each subquery. Make subquery a piece of pipeline. +class CreatingSetsTransform : public IProcessor +{ +public: + CreatingSetsTransform( + Block out_header, + const SubqueriesForSets & subqueries_for_sets_, + const SizeLimits & network_transfer_limits, + const Context & context); + + String getName() const override { return "CreatingSetsTransform"; } + Status prepare() override; + void work() override; + + void setProgressCallback(const ProgressCallback & callback); + void setProcessListElement(QueryStatus * status); + +protected: + bool finished = false; + +private: + SubqueriesForSets subqueries_for_sets; + SubqueriesForSets::iterator cur_subquery; + + bool started_cur_subquery = false; + BlockOutputStreamPtr table_out; + UInt64 elapsed_nanoseconds = 0; + + bool done_with_set = true; + bool done_with_join = true; + bool done_with_table = true; + + SizeLimits network_transfer_limits; + const Context & context; + + size_t rows_to_transfer = 0; + size_t bytes_to_transfer = 0; + + using Logger = Poco::Logger; + Logger * log = &Logger::get("CreatingSetsBlockInputStream"); + + bool is_initialized = false; + + void init(); + void startSubquery(SubqueryForSet & subquery); + void finishSubquery(SubqueryForSet & subquery); +}; + +} diff --git a/dbms/src/Processors/Transforms/CubeTransform.cpp b/dbms/src/Processors/Transforms/CubeTransform.cpp new file mode 100644 index 00000000000..5809a480d09 --- /dev/null +++ b/dbms/src/Processors/Transforms/CubeTransform.cpp @@ -0,0 +1,61 @@ +#include +#include + +namespace DB +{ + +CubeTransform::CubeTransform(Block header, AggregatingTransformParamsPtr params_) + : IInflatingTransform(std::move(header), params_->getHeader()) + , params(std::move(params_)) + , keys(params->params.keys) +{ + if (keys.size() >= 8 * sizeof(mask)) + throw Exception("Too many keys are used for CubeTransform.", ErrorCodes::LOGICAL_ERROR); +} + +void CubeTransform::consume(Chunk chunk) +{ + consumed_chunk = std::move(chunk); + auto num_rows = consumed_chunk.getNumRows(); + mask = (UInt64(1) << keys.size()) - 1; + + current_columns = consumed_chunk.getColumns(); + current_zero_columns.clear(); + current_zero_columns.reserve(keys.size()); + + for (auto key : keys) + current_zero_columns.emplace_back(current_columns[key]->cloneEmpty()->cloneResized(num_rows)); +} + +bool CubeTransform::canGenerate() +{ + return consumed_chunk; +} + +Chunk CubeTransform::generate() +{ + auto gen_chunk = std::move(consumed_chunk); + + if (mask) + { + --mask; + + auto columns = current_columns; + auto size = keys.size(); + for (size_t i = 0; i < size; ++i) + /// Reverse bit order to support previous behaviour. + if ((mask & (UInt64(1) << (size - i - 1))) == 0) + columns[keys[i]] = current_zero_columns[i]; + + BlocksList cube_blocks = { getInputPort().getHeader().cloneWithColumns(columns) }; + auto cube_block = params->aggregator.mergeBlocks(cube_blocks, false); + + auto num_rows = cube_block.rows(); + consumed_chunk = Chunk(cube_block.getColumns(), num_rows); + } + + finalizeChunk(gen_chunk); + return gen_chunk; +} + +} diff --git a/dbms/src/Processors/Transforms/CubeTransform.h b/dbms/src/Processors/Transforms/CubeTransform.h new file mode 100644 index 00000000000..60259832e40 --- /dev/null +++ b/dbms/src/Processors/Transforms/CubeTransform.h @@ -0,0 +1,35 @@ +#pragma once +#include +#include + + +namespace DB +{ + +/// Takes blocks after grouping, with non-finalized aggregate functions. +/// Calculates all subsets of columns and aggregates over them. +class CubeTransform : public IInflatingTransform +{ +public: + CubeTransform(Block header, AggregatingTransformParamsPtr params); + String getName() const override { return "CubeTransform"; } + +protected: + void consume(Chunk chunk) override; + + bool canGenerate() override; + + Chunk generate() override; + +private: + AggregatingTransformParamsPtr params; + ColumnNumbers keys; + + Chunk consumed_chunk; + Columns current_columns; + Columns current_zero_columns; + + UInt64 mask = 0; +}; + +} diff --git a/dbms/src/Processors/Transforms/DistinctTransform.cpp b/dbms/src/Processors/Transforms/DistinctTransform.cpp new file mode 100644 index 00000000000..7cd9a54e055 --- /dev/null +++ b/dbms/src/Processors/Transforms/DistinctTransform.cpp @@ -0,0 +1,114 @@ +#include + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int SET_SIZE_LIMIT_EXCEEDED; +} + +DistinctTransform::DistinctTransform( + const Block & header, + const SizeLimits & set_size_limits, + UInt64 limit_hint, + const Names & columns) + : ISimpleTransform(header, header, true) + , limit_hint(limit_hint) + , set_size_limits(set_size_limits) +{ + size_t num_columns = columns.empty() ? header.columns() : columns.size(); + + key_columns_pos.reserve(columns.size()); + for (size_t i = 0; i < num_columns; ++i) + { + auto pos = columns.empty() ? i + : header.getPositionByName(columns[i]); + + auto & col = header.getByPosition(pos).column; + + if (!(col && isColumnConst(*col))) + key_columns_pos.emplace_back(pos); + } +} + +template +void DistinctTransform::buildFilter( + Method & method, + const ColumnRawPtrs & columns, + IColumn::Filter & filter, + size_t rows, + SetVariants & variants) const +{ + typename Method::State state(columns, key_sizes, nullptr); + + for (size_t i = 0; i < rows; ++i) + { + auto emplace_result = state.emplaceKey(method.data, i, variants.string_pool); + + /// Emit the record if there is no such key in the current set yet. + /// Skip it otherwise. + filter[i] = emplace_result.isInserted(); + } +} + +void DistinctTransform::transform(Chunk & chunk) +{ + auto num_rows = chunk.getNumRows(); + auto columns = chunk.detachColumns(); + + /// Stop reading if we already reach the limit. + if (no_more_rows || (limit_hint && data.getTotalRowCount() >= limit_hint)) + { + stopReading(); + return; + } + + ColumnRawPtrs column_ptrs; + column_ptrs.reserve(key_columns_pos.size()); + for (auto pos : key_columns_pos) + column_ptrs.emplace_back(columns[pos].get()); + + if (column_ptrs.empty()) + { + /// Only constants. We need to return single row. + no_more_rows = true; + for (auto & column : columns) + column = column->cut(0, 1); + + chunk.setColumns(std::move(columns), 1); + return; + } + + if (data.empty()) + data.init(SetVariants::chooseMethod(column_ptrs, key_sizes)); + + const auto old_set_size = data.getTotalRowCount(); + IColumn::Filter filter(num_rows); + + switch (data.type) + { + case SetVariants::Type::EMPTY: + break; +#define M(NAME) \ + case SetVariants::Type::NAME: \ + buildFilter(*data.NAME, column_ptrs, filter, num_rows, data); \ + break; + APPLY_FOR_SET_VARIANTS(M) +#undef M + } + + /// Just go to the next chunk if there isn't any new record in the current one. + if (data.getTotalRowCount() == old_set_size) + return; + + if (!set_size_limits.check(data.getTotalRowCount(), data.getTotalByteCount(), "DISTINCT", ErrorCodes::SET_SIZE_LIMIT_EXCEEDED)) + return; + + for (auto & column : columns) + column = column->filter(filter, -1); + + chunk.setColumns(std::move(columns), data.getTotalRowCount() - old_set_size); +} + +} diff --git a/dbms/src/Processors/Transforms/DistinctTransform.h b/dbms/src/Processors/Transforms/DistinctTransform.h new file mode 100644 index 00000000000..05ef9e9c334 --- /dev/null +++ b/dbms/src/Processors/Transforms/DistinctTransform.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include +#include +#include + +namespace DB +{ + +class DistinctTransform : public ISimpleTransform +{ +public: + DistinctTransform( + const Block & header, + const SizeLimits & set_size_limits, + UInt64 limit_hint, + const Names & columns); + + String getName() const override { return "DistinctTransform"; } + +protected: + void transform(Chunk & chunk) override; + +private: + ColumnNumbers key_columns_pos; + SetVariants data; + Sizes key_sizes; + UInt64 limit_hint; + + bool no_more_rows = false; + + /// Restrictions on the maximum size of the output data. + SizeLimits set_size_limits; + + template + void buildFilter( + Method & method, + const ColumnRawPtrs & key_columns, + IColumn::Filter & filter, + size_t rows, + SetVariants & variants) const; +}; + +} diff --git a/dbms/src/Processors/Transforms/ExpressionTransform.cpp b/dbms/src/Processors/Transforms/ExpressionTransform.cpp new file mode 100644 index 00000000000..c42ef92b085 --- /dev/null +++ b/dbms/src/Processors/Transforms/ExpressionTransform.cpp @@ -0,0 +1,40 @@ +#include +#include + +namespace DB +{ + +static Block transformHeader(Block header, const ExpressionActionsPtr & expression) +{ + expression->execute(header, true); + return header; +} + + +ExpressionTransform::ExpressionTransform(const Block & header, ExpressionActionsPtr expression, bool on_totals, bool default_totals) + : ISimpleTransform(header, transformHeader(header, expression), on_totals) + , expression(std::move(expression)) + , on_totals(on_totals) + , default_totals(default_totals) +{ +} + +void ExpressionTransform::transform(Chunk & chunk) +{ + auto block = getInputPort().getHeader().cloneWithColumns(chunk.detachColumns()); + + if (on_totals) + { + if (default_totals && !expression->hasTotalsInJoin()) + return; + + expression->executeOnTotals(block); + } + else + expression->execute(block); + + auto num_rows = block.rows(); + chunk.setColumns(block.getColumns(), num_rows); +} + +} diff --git a/dbms/src/Processors/Transforms/ExpressionTransform.h b/dbms/src/Processors/Transforms/ExpressionTransform.h new file mode 100644 index 00000000000..8face634f96 --- /dev/null +++ b/dbms/src/Processors/Transforms/ExpressionTransform.h @@ -0,0 +1,26 @@ +#pragma once +#include + +namespace DB +{ + +class ExpressionActions; +using ExpressionActionsPtr = std::shared_ptr; + +class ExpressionTransform : public ISimpleTransform +{ +public: + ExpressionTransform(const Block & header, ExpressionActionsPtr expression, bool on_totals = false, bool default_totals = false); + + String getName() const override { return "ExpressionTransform"; } + +protected: + void transform(Chunk & chunk) override; + +private: + ExpressionActionsPtr expression; + bool on_totals; + bool default_totals; +}; + +} diff --git a/dbms/src/Processors/Transforms/ExtremesTransform.cpp b/dbms/src/Processors/Transforms/ExtremesTransform.cpp new file mode 100644 index 00000000000..82a7605fa11 --- /dev/null +++ b/dbms/src/Processors/Transforms/ExtremesTransform.cpp @@ -0,0 +1,121 @@ +#include + +namespace DB +{ + +ExtremesTransform::ExtremesTransform(const Block & header) + : ISimpleTransform(header, header, true) +{ + /// Port for Extremes. + outputs.emplace_back(outputs.front().getHeader(), this); +} + +IProcessor::Status ExtremesTransform::prepare() +{ + if (!finished_transform) + { + auto status = ISimpleTransform::prepare(); + + if (status != Status::Finished) + return status; + + finished_transform = true; + } + + auto & totals_output = getExtremesPort(); + + /// Check can output. + if (totals_output.isFinished()) + return Status::Finished; + + if (!totals_output.canPush()) + return Status::PortFull; + + if (!extremes && !extremes_columns.empty()) + return Status::Ready; + + if (extremes) + totals_output.push(std::move(extremes)); + + totals_output.finish(); + return Status::Finished; +} + +void ExtremesTransform::work() +{ + if (finished_transform) + { + if (!extremes && !extremes_columns.empty()) + extremes.setColumns(std::move(extremes_columns), 2); + } + else + ISimpleTransform::work(); +} + +void ExtremesTransform::transform(DB::Chunk & chunk) +{ + + if (chunk.getNumRows() == 0) + return; + + size_t num_columns = chunk.getNumColumns(); + auto & columns = chunk.getColumns(); + + if (extremes_columns.empty()) + { + extremes_columns.resize(num_columns); + + for (size_t i = 0; i < num_columns; ++i) + { + const ColumnPtr & src = columns[i]; + + if (isColumnConst(*src)) + { + /// Equal min and max. + extremes_columns[i] = src->cloneResized(2); + } + else + { + Field min_value; + Field max_value; + + src->getExtremes(min_value, max_value); + + extremes_columns[i] = src->cloneEmpty(); + + extremes_columns[i]->insert(min_value); + extremes_columns[i]->insert(max_value); + } + } + } + else + { + for (size_t i = 0; i < num_columns; ++i) + { + if (isColumnConst(*extremes_columns[i])) + continue; + + Field min_value = (*extremes_columns[i])[0]; + Field max_value = (*extremes_columns[i])[1]; + + Field cur_min_value; + Field cur_max_value; + + columns[i]->getExtremes(cur_min_value, cur_max_value); + + if (cur_min_value < min_value) + min_value = cur_min_value; + if (cur_max_value > max_value) + max_value = cur_max_value; + + MutableColumnPtr new_extremes = extremes_columns[i]->cloneEmpty(); + + new_extremes->insert(min_value); + new_extremes->insert(max_value); + + extremes_columns[i] = std::move(new_extremes); + } + } +} + +} diff --git a/dbms/src/Processors/Transforms/ExtremesTransform.h b/dbms/src/Processors/Transforms/ExtremesTransform.h new file mode 100644 index 00000000000..d447e8c9cfa --- /dev/null +++ b/dbms/src/Processors/Transforms/ExtremesTransform.h @@ -0,0 +1,30 @@ +#include + +namespace DB +{ + +class ExtremesTransform : public ISimpleTransform +{ + +public: + explicit ExtremesTransform(const Block & header); + + String getName() const override { return "ExtremesTransform"; } + + OutputPort & getExtremesPort() { return outputs.back(); } + + Status prepare() override; + void work() override; + +protected: + void transform(Chunk & chunk) override; + + bool finished_transform = false; + Chunk extremes; + +private: + MutableColumns extremes_columns; +}; + +} + diff --git a/dbms/src/Processors/Transforms/FilterTransform.cpp b/dbms/src/Processors/Transforms/FilterTransform.cpp new file mode 100644 index 00000000000..725b5ceb01b --- /dev/null +++ b/dbms/src/Processors/Transforms/FilterTransform.cpp @@ -0,0 +1,199 @@ +#include +#include +#include + +namespace DB +{ + +static void replaceFilterToConstant(Block & block, const String & filter_column_name) +{ + ConstantFilterDescription constant_filter_description; + + auto filter_column = block.getPositionByName(filter_column_name); + auto & column_elem = block.safeGetByPosition(filter_column); + + /// Isn't the filter already constant? + if (column_elem.column) + constant_filter_description = ConstantFilterDescription(*column_elem.column); + + if (!constant_filter_description.always_false + && !constant_filter_description.always_true) + { + /// Replace the filter column to a constant with value 1. + FilterDescription filter_description_check(*column_elem.column); + column_elem.column = column_elem.type->createColumnConst(block.rows(), 1u); + } +} + +static Block transformHeader( + Block header, + const ExpressionActionsPtr & expression, + const String & filter_column_name, + bool remove_filter_column) +{ + expression->execute(header); + + if (remove_filter_column) + header.erase(filter_column_name); + else + replaceFilterToConstant(header, filter_column_name); + + return header; +} + +FilterTransform::FilterTransform( + const Block & header, + ExpressionActionsPtr expression_, + String filter_column_name_, + bool remove_filter_column) + : ISimpleTransform(header, transformHeader(header, expression_, filter_column_name_, remove_filter_column), true) + , expression(std::move(expression_)) + , filter_column_name(std::move(filter_column_name_)) + , remove_filter_column(remove_filter_column) +{ + transformed_header = getInputPort().getHeader(); + expression->execute(transformed_header); + filter_column_position = transformed_header.getPositionByName(filter_column_name); + + auto & column = transformed_header.getByPosition(filter_column_position).column; + if (column) + constant_filter_description = ConstantFilterDescription(*column); +} + +IProcessor::Status FilterTransform::prepare() +{ + if (constant_filter_description.always_false) + { + input.close(); + output.finish(); + return Status::Finished; + } + + return ISimpleTransform::prepare(); +} + + +void FilterTransform::removeFilterIfNeed(Chunk & chunk) +{ + if (chunk && remove_filter_column) + chunk.erase(filter_column_position); +} + +void FilterTransform::transform(Chunk & chunk) +{ + size_t num_rows_before_filtration = chunk.getNumRows(); + auto columns = chunk.detachColumns(); + + { + Block block = getInputPort().getHeader().cloneWithColumns(columns); + columns.clear(); + expression->execute(block); + num_rows_before_filtration = block.rows(); + columns = block.getColumns(); + } + + if (constant_filter_description.always_true) + { + chunk.setColumns(std::move(columns), num_rows_before_filtration); + removeFilterIfNeed(chunk); + return; + } + + size_t num_columns = columns.size(); + ColumnPtr filter_column = columns[filter_column_position]; + + /** It happens that at the stage of analysis of expressions (in sample_block) the columns-constants have not been calculated yet, + * and now - are calculated. That is, not all cases are covered by the code above. + * This happens if the function returns a constant for a non-constant argument. + * For example, `ignore` function. + */ + constant_filter_description = ConstantFilterDescription(*filter_column); + + if (constant_filter_description.always_false) + return; /// Will finish at next prepare call + + if (constant_filter_description.always_true) + { + chunk.setColumns(std::move(columns), num_rows_before_filtration); + removeFilterIfNeed(chunk); + return; + } + + FilterDescription filter_and_holder(*filter_column); + + /** Let's find out how many rows will be in result. + * To do this, we filter out the first non-constant column + * or calculate number of set bytes in the filter. + */ + size_t first_non_constant_column = num_columns; + for (size_t i = 0; i < num_columns; ++i) + { + if (!isColumnConst(*columns[i])) + { + first_non_constant_column = i; + break; + } + } + + size_t num_filtered_rows = 0; + if (first_non_constant_column != num_columns) + { + columns[first_non_constant_column] = columns[first_non_constant_column]->filter(*filter_and_holder.data, -1); + num_filtered_rows = columns[first_non_constant_column]->size(); + } + else + num_filtered_rows = countBytesInFilter(*filter_and_holder.data); + + /// If the current block is completely filtered out, let's move on to the next one. + if (num_filtered_rows == 0) + /// SimpleTransform will skip it. + return; + + /// If all the rows pass through the filter. + if (num_filtered_rows == num_rows_before_filtration) + { + if (!remove_filter_column) + { + /// Replace the column with the filter by a constant. + auto & type = transformed_header.getByPosition(filter_column_position).type; + columns[filter_column_position] = type->createColumnConst(num_filtered_rows, 1u); + } + + /// No need to touch the rest of the columns. + chunk.setColumns(std::move(columns), num_rows_before_filtration); + removeFilterIfNeed(chunk); + return; + } + + /// Filter the rest of the columns. + for (size_t i = 0; i < num_columns; ++i) + { + const auto & current_type = transformed_header.safeGetByPosition(i).type; + auto & current_column = columns[i]; + + if (i == filter_column_position) + { + /// The column with filter itself is replaced with a column with a constant `1`, since after filtering, nothing else will remain. + /// NOTE User could pass column with something different than 0 and 1 for filter. + /// Example: + /// SELECT materialize(100) AS x WHERE x + /// will work incorrectly. + current_column = current_type->createColumnConst(num_filtered_rows, 1u); + continue; + } + + if (i == first_non_constant_column) + continue; + + if (isColumnConst(*current_column)) + current_column = current_column->cut(0, num_filtered_rows); + else + current_column = current_column->filter(*filter_and_holder.data, num_filtered_rows); + } + + chunk.setColumns(std::move(columns), num_filtered_rows); + removeFilterIfNeed(chunk); +} + + +} diff --git a/dbms/src/Processors/Transforms/FilterTransform.h b/dbms/src/Processors/Transforms/FilterTransform.h new file mode 100644 index 00000000000..32cdbb79d50 --- /dev/null +++ b/dbms/src/Processors/Transforms/FilterTransform.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include + +namespace DB +{ + +class ExpressionActions; +using ExpressionActionsPtr = std::shared_ptr; + +/** Has one input and one output. + * Simply pull a block from input, transform it, and push it to output. + * If remove_filter_column is true, remove filter column from block. + */ +class FilterTransform : public ISimpleTransform +{ +public: + FilterTransform( + const Block & header, ExpressionActionsPtr expression, String filter_column_name, bool remove_filter_column); + + String getName() const override { return "FilterTransform"; } + + Status prepare() override; + +protected: + void transform(Chunk & chunk) override; + +private: + ExpressionActionsPtr expression; + String filter_column_name; + bool remove_filter_column; + + ConstantFilterDescription constant_filter_description; + size_t filter_column_position = 0; + + /// Header after expression, but before removing filter column. + Block transformed_header; + + void removeFilterIfNeed(Chunk & chunk); +}; + +} diff --git a/dbms/src/Processors/Transforms/LimitByTransform.cpp b/dbms/src/Processors/Transforms/LimitByTransform.cpp new file mode 100644 index 00000000000..83268d178bd --- /dev/null +++ b/dbms/src/Processors/Transforms/LimitByTransform.cpp @@ -0,0 +1,70 @@ +#include +#include + +namespace DB +{ + +LimitByTransform::LimitByTransform(const Block & header, size_t group_length_, size_t group_offset_, const Names & columns) + : ISimpleTransform(header, header, true) + , group_length(group_length_) + , group_offset(group_offset_) +{ + key_positions.reserve(columns.size()); + + for (const auto & name : columns) + { + auto position = header.getPositionByName(name); + auto & column = header.getByPosition(position).column; + + /// Ignore all constant columns. + if (!(column && isColumnConst(*column))) + key_positions.emplace_back(position); + } +} + +void LimitByTransform::transform(Chunk & chunk) +{ + size_t num_rows = chunk.getNumRows(); + auto columns = chunk.detachColumns(); + + IColumn::Filter filter(num_rows); + size_t inserted_count = 0; + + for (size_t row = 0; row < num_rows; ++row) + { + UInt128 key(0, 0); + SipHash hash; + + for (auto position : key_positions) + columns[position]->updateHashWithValue(row, hash); + + hash.get128(key.low, key.high); + + auto count = keys_counts[key]++; + if (count >= group_offset && count < group_length + group_offset) + { + inserted_count++; + filter[row] = 1; + } + else + filter[row] = 0; + } + + /// Just go to the next block if there isn't any new records in the current one. + if (!inserted_count) + /// SimpleTransform will skip it. + return; + + if (inserted_count < num_rows) + { + for (auto & column : columns) + if (isColumnConst(*column)) + column = column->cut(0, inserted_count); + else + column = column->filter(filter, inserted_count); + } + + chunk.setColumns(std::move(columns), inserted_count); +} + +} diff --git a/dbms/src/Processors/Transforms/LimitByTransform.h b/dbms/src/Processors/Transforms/LimitByTransform.h new file mode 100644 index 00000000000..344cf6feea4 --- /dev/null +++ b/dbms/src/Processors/Transforms/LimitByTransform.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include +#include + +namespace DB +{ + +class LimitByTransform : public ISimpleTransform +{ +public: + LimitByTransform(const Block & header, size_t group_length_, size_t group_offset_, const Names & columns); + + String getName() const override { return "LimitByTransform"; } + +protected: + void transform(Chunk & chunk) override; + +private: + using MapHashed = HashMap; + + MapHashed keys_counts; + std::vector key_positions; + const size_t group_length; + const size_t group_offset; +}; + +} diff --git a/dbms/src/Processors/Transforms/LimitsCheckingTransform.cpp b/dbms/src/Processors/Transforms/LimitsCheckingTransform.cpp new file mode 100644 index 00000000000..092327a0d8e --- /dev/null +++ b/dbms/src/Processors/Transforms/LimitsCheckingTransform.cpp @@ -0,0 +1,115 @@ +#include +#include + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int TOO_MANY_ROWS; + extern const int TOO_MANY_BYTES; + extern const int TOO_MANY_ROWS_OR_BYTES; + extern const int TIMEOUT_EXCEEDED; + extern const int TOO_SLOW; + extern const int LOGICAL_ERROR; + extern const int BLOCKS_HAVE_DIFFERENT_STRUCTURE; + extern const int TOO_DEEP_PIPELINE; +} + + +static bool handleOverflowMode(OverflowMode mode, const String & message, int code) +{ + switch (mode) + { + case OverflowMode::THROW: + throw Exception(message, code); + case OverflowMode::BREAK: + return false; + default: + throw Exception("Logical error: unknown overflow mode", ErrorCodes::LOGICAL_ERROR); + } +} + + +void ProcessorProfileInfo::update(const Chunk & block) +{ + ++blocks; + rows += block.getNumRows(); + bytes += block.bytes(); +} + +LimitsCheckingTransform::LimitsCheckingTransform(const Block & header, LocalLimits limits) + : ISimpleTransform(header, header, false) + , limits(std::move(limits)) +{ +} + +//LimitsCheckingTransform::LimitsCheckingTransform(const Block & header, LocalLimits limits, QueryStatus * process_list_elem) +// : ISimpleTransform(header, header, false) +// , limits(std::move(limits)) +// , process_list_elem(process_list_elem) +//{ +//} + +void LimitsCheckingTransform::transform(Chunk & chunk) +{ + if (!info.started) + { + info.total_stopwatch.start(); + info.started = true; + } + + if (!checkTimeLimit()) + { + stopReading(); + return; + } + + if (chunk) + { + info.update(chunk); + + if (limits.mode == LimitsMode::LIMITS_CURRENT && + !limits.size_limits.check(info.rows, info.bytes, "result", ErrorCodes::TOO_MANY_ROWS_OR_BYTES)) + stopReading(); + + if (quota != nullptr) + checkQuota(chunk); + } +} + +bool LimitsCheckingTransform::checkTimeLimit() +{ + if (limits.max_execution_time != 0 + && info.total_stopwatch.elapsed() > static_cast(limits.max_execution_time.totalMicroseconds()) * 1000) + return handleOverflowMode(limits.timeout_overflow_mode, + "Timeout exceeded: elapsed " + toString(info.total_stopwatch.elapsedSeconds()) + + " seconds, maximum: " + toString(limits.max_execution_time.totalMicroseconds() / 1000000.0), + ErrorCodes::TIMEOUT_EXCEEDED); + + return true; +} + +void LimitsCheckingTransform::checkQuota(Chunk & chunk) +{ + switch (limits.mode) + { + case LimitsMode::LIMITS_TOTAL: + /// Checked in `progress` method. + break; + + case LimitsMode::LIMITS_CURRENT: + { + time_t current_time = time(nullptr); + double total_elapsed = info.total_stopwatch.elapsedSeconds(); + + quota->checkAndAddResultRowsBytes(current_time, chunk.getNumRows(), chunk.bytes()); + quota->checkAndAddExecutionTime(current_time, Poco::Timespan((total_elapsed - prev_elapsed) * 1000000.0)); + + prev_elapsed = total_elapsed; + break; + } + } +} + +} diff --git a/dbms/src/Processors/Transforms/LimitsCheckingTransform.h b/dbms/src/Processors/Transforms/LimitsCheckingTransform.h new file mode 100644 index 00000000000..a08e9ea9c67 --- /dev/null +++ b/dbms/src/Processors/Transforms/LimitsCheckingTransform.h @@ -0,0 +1,56 @@ +#pragma once +#include +#include +#include +#include + +#include + +namespace DB +{ + +/// Information for profiling. +struct ProcessorProfileInfo +{ + bool started = false; + Stopwatch total_stopwatch {CLOCK_MONOTONIC_COARSE}; /// Time with waiting time + + size_t rows = 0; + size_t blocks = 0; + size_t bytes = 0; + + void update(const Chunk & block); +}; + +class LimitsCheckingTransform : public ISimpleTransform +{ +public: + + using LocalLimits = IBlockInputStream::LocalLimits; + using LimitsMode = IBlockInputStream::LimitsMode; + + /// LIMITS_CURRENT + LimitsCheckingTransform(const Block & header, LocalLimits limits); + /// LIMITS_TOTAL + /// LimitsCheckingTransform(const Block & header, LocalLimits limits, QueryStatus * process_list_elem); + + String getName() const override { return "LimitsCheckingTransform"; } + + void setQuota(QuotaForIntervals & quota_) { quota = "a_; } + +protected: + void transform(Chunk & chunk) override; + +private: + LocalLimits limits; + + QuotaForIntervals * quota = nullptr; + double prev_elapsed = 0; + + ProcessorProfileInfo info; + + bool checkTimeLimit(); + void checkQuota(Chunk & chunk); +}; + +} diff --git a/dbms/src/Processors/Transforms/MaterializingTransform.cpp b/dbms/src/Processors/Transforms/MaterializingTransform.cpp new file mode 100644 index 00000000000..f13d5376ebe --- /dev/null +++ b/dbms/src/Processors/Transforms/MaterializingTransform.cpp @@ -0,0 +1,21 @@ +#include +#include + +namespace DB +{ + +MaterializingTransform::MaterializingTransform(const Block & header) + : ISimpleTransform(header, materializeBlock(header), false) {} + +void MaterializingTransform::transform(Chunk & chunk) +{ + auto num_rows = chunk.getNumRows(); + auto columns = chunk.detachColumns(); + + for (auto & col : columns) + col = col->convertToFullColumnIfConst(); + + chunk.setColumns(std::move(columns), num_rows); +} + +} diff --git a/dbms/src/Processors/Transforms/MaterializingTransform.h b/dbms/src/Processors/Transforms/MaterializingTransform.h new file mode 100644 index 00000000000..914dc268021 --- /dev/null +++ b/dbms/src/Processors/Transforms/MaterializingTransform.h @@ -0,0 +1,18 @@ +#include + +namespace DB +{ + +/// Converts columns-constants to full columns ("materializes" them). +class MaterializingTransform : public ISimpleTransform +{ +public: + explicit MaterializingTransform(const Block & header); + + String getName() const override { return "MaterializingTransform"; } + +protected: + void transform(Chunk & chunk) override; +}; + +} diff --git a/dbms/src/Processors/Transforms/MergeSortingTransform.cpp b/dbms/src/Processors/Transforms/MergeSortingTransform.cpp new file mode 100644 index 00000000000..8591f5447f7 --- /dev/null +++ b/dbms/src/Processors/Transforms/MergeSortingTransform.cpp @@ -0,0 +1,659 @@ +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + + +namespace ProfileEvents +{ + extern const Event ExternalSortWritePart; + extern const Event ExternalSortMerge; +} + + +namespace DB +{ + +class BufferingToFileTransform : public IAccumulatingTransform +{ +public: + BufferingToFileTransform(const Block & header, Logger * log_, std::string path_) + : IAccumulatingTransform(header, header), log(log_) + , path(std::move(path_)), file_buf_out(path), compressed_buf_out(file_buf_out) + , out_stream(std::make_shared(compressed_buf_out, 0, header)) + { + LOG_INFO(log, "Sorting and writing part of data into temporary file " + path); + ProfileEvents::increment(ProfileEvents::ExternalSortWritePart); + out_stream->writePrefix(); + } + + String getName() const override { return "BufferingToFileTransform"; } + + void consume(Chunk chunk) override + { + out_stream->write(getInputPort().getHeader().cloneWithColumns(chunk.detachColumns())); + } + + Chunk generate() override + { + if (out_stream) + { + out_stream->writeSuffix(); + compressed_buf_out.next(); + file_buf_out.next(); + LOG_INFO(log, "Done writing part of data into temporary file " + path); + + out_stream.reset(); + + file_in = std::make_unique(path); + compressed_in = std::make_unique(*file_in); + block_in = std::make_shared(*compressed_in, getOutputPort().getHeader(), 0); + } + + if (!block_in) + return {}; + + auto block = block_in->read(); + if (!block) + { + block_in->readSuffix(); + block_in.reset(); + return {}; + } + + UInt64 num_rows = block.rows(); + return Chunk(block.getColumns(), num_rows); + } + +private: + Logger * log; + std::string path; + WriteBufferFromFile file_buf_out; + CompressedWriteBuffer compressed_buf_out; + BlockOutputStreamPtr out_stream; + + std::unique_ptr file_in; + std::unique_ptr compressed_in; + BlockInputStreamPtr block_in; +}; + +/** Part of implementation. Merging array of ready (already read from somewhere) chunks. + * Returns result of merge as stream of chunks, not more than 'max_merged_block_size' rows in each. + */ +class MergeSorter +{ +public: + MergeSorter(Chunks chunks_, SortDescription & description_, size_t max_merged_block_size_, UInt64 limit_); + + Chunk read(); + +private: + Chunks chunks; + SortDescription description; + size_t max_merged_block_size; + UInt64 limit; + size_t total_merged_rows = 0; + + using CursorImpls = std::vector; + CursorImpls cursors; + + bool has_collation = false; + + std::priority_queue queue_without_collation; + std::priority_queue queue_with_collation; + + /** Two different cursors are supported - with and without Collation. + * Templates are used (instead of virtual functions in SortCursor) for zero-overhead. + */ + template + Chunk mergeImpl(std::priority_queue & queue); +}; + +class MergeSorterSource : public ISource +{ +public: + MergeSorterSource(Block header, Chunks chunks, SortDescription & description, size_t max_merged_block_size, UInt64 limit) + : ISource(std::move(header)), merge_sorter(std::move(chunks), description, max_merged_block_size, limit) {} + + String getName() const override { return "MergeSorterSource"; } + +protected: + Chunk generate() override { return merge_sorter.read(); } + +private: + MergeSorter merge_sorter; +}; + +MergeSorter::MergeSorter(Chunks chunks_, SortDescription & description_, size_t max_merged_block_size_, UInt64 limit_) + : chunks(std::move(chunks_)), description(description_), max_merged_block_size(max_merged_block_size_), limit(limit_) +{ + Chunks nonempty_chunks; + for (auto & chunk : chunks) + { + if (chunk.getNumRows() == 0) + continue; + + cursors.emplace_back(chunk.getColumns(), description); + has_collation |= cursors.back().has_collation; + + nonempty_chunks.emplace_back(std::move(chunk)); + } + + chunks.swap(nonempty_chunks); + + if (!has_collation) + { + for (auto & cursor : cursors) + queue_without_collation.push(SortCursor(&cursor)); + } + else + { + for (auto & cursor : cursors) + queue_with_collation.push(SortCursorWithCollation(&cursor)); + } +} + + +Chunk MergeSorter::read() +{ + if (chunks.empty()) + return Chunk(); + + if (chunks.size() == 1) + { + auto res = std::move(chunks[0]); + chunks.clear(); + return res; + } + + return !has_collation + ? mergeImpl(queue_without_collation) + : mergeImpl(queue_with_collation); +} + + +template +Chunk MergeSorter::mergeImpl(std::priority_queue & queue) +{ + size_t num_columns = chunks[0].getNumColumns(); + + MutableColumns merged_columns = chunks[0].cloneEmptyColumns(); + /// TODO: reserve (in each column) + + /// Take rows from queue in right order and push to 'merged'. + size_t merged_rows = 0; + while (!queue.empty()) + { + TSortCursor current = queue.top(); + queue.pop(); + + for (size_t i = 0; i < num_columns; ++i) + merged_columns[i]->insertFrom(*current->all_columns[i], current->pos); + + ++total_merged_rows; + ++merged_rows; + + if (!current->isLast()) + { + current->next(); + queue.push(current); + } + + if (limit && total_merged_rows == limit) + { + chunks.clear(); + return Chunk(std::move(merged_columns), merged_rows); + } + + if (merged_rows == max_merged_block_size) + return Chunk(std::move(merged_columns), merged_rows); + } + + chunks.clear(); + + if (merged_rows == 0) + return {}; + + return Chunk(std::move(merged_columns), merged_rows); +} + + +MergeSortingTransform::MergeSortingTransform( + const Block & header, + SortDescription & description_, + size_t max_merged_block_size_, UInt64 limit_, + size_t max_bytes_before_remerge_, + size_t max_bytes_before_external_sort_, const std::string & tmp_path_) + : IProcessor({header}, {header}) + , description(description_), max_merged_block_size(max_merged_block_size_), limit(limit_) + , max_bytes_before_remerge(max_bytes_before_remerge_) + , max_bytes_before_external_sort(max_bytes_before_external_sort_), tmp_path(tmp_path_) +{ + auto & sample = inputs.front().getHeader(); + + /// Replace column names to column position in sort_description. + for (auto & column_description : description) + { + if (!column_description.column_name.empty()) + { + column_description.column_number = sample.getPositionByName(column_description.column_name); + column_description.column_name.clear(); + } + } + + /// Remove constants from header and map old indexes to new. + size_t num_columns = sample.columns(); + ColumnNumbers map(num_columns, num_columns); + const_columns_to_remove.assign(num_columns, true); + for (size_t pos = 0; pos < num_columns; ++pos) + { + const auto & column = sample.getByPosition(pos); + if (!(column.column && isColumnConst(*column.column))) + { + map[pos] = header_without_constants.columns(); + header_without_constants.insert(column); + const_columns_to_remove[pos] = false; + } + } + + /// Remove constants from column_description and remap positions. + SortDescription description_without_constants; + description_without_constants.reserve(description.size()); + for (const auto & column_description : description) + { + auto old_pos = column_description.column_number; + auto new_pos = map[old_pos]; + if (new_pos < num_columns) + { + description_without_constants.push_back(column_description); + description_without_constants.back().column_number = new_pos; + } + } + + description.swap(description_without_constants); +} + +MergeSortingTransform::~MergeSortingTransform() = default; + +IProcessor::Status MergeSortingTransform::prepare() +{ + if (stage == Stage::Serialize) + { + if (!processors.empty()) + return Status::ExpandPipeline; + + auto status = prepareSerialize(); + if (status != Status::Finished) + return status; + + stage = Stage::Consume; + } + + if (stage == Stage::Consume) + { + auto status = prepareConsume(); + if (status != Status::Finished) + return status; + + stage = Stage::Generate; + } + + /// stage == Stage::Generate + + if (!generated_prefix) + return Status::Ready; + + if (!processors.empty()) + return Status::ExpandPipeline; + + return prepareGenerate(); +} + +IProcessor::Status MergeSortingTransform::prepareConsume() +{ + auto & input = inputs.front(); + auto & output = outputs.front(); + + /// Check can output. + + if (output.isFinished()) + { + input.close(); + return Status::Finished; + } + + if (!output.canPush()) + { + input.setNotNeeded(); + return Status::PortFull; + } + + if (generated_chunk) + output.push(std::move(generated_chunk)); + + /// Check can input. + if (!current_chunk) + { + if (input.isFinished()) + return Status::Finished; + + input.setNeeded(); + + if (!input.hasData()) + return Status::NeedData; + + current_chunk = input.pull(); + } + + /// Now consume. + return Status::Ready; +} + +IProcessor::Status MergeSortingTransform::prepareSerialize() +{ + auto & output = outputs.back(); + + if (output.isFinished()) + return Status::Finished; + + if (!output.canPush()) + return Status::PortFull; + + if (current_chunk) + output.push(std::move(current_chunk)); + + if (merge_sorter) + return Status::Ready; + + output.finish(); + return Status::Finished; +} + +IProcessor::Status MergeSortingTransform::prepareGenerate() +{ + auto & output = outputs.front(); + + if (output.isFinished()) + return Status::Finished; + + if (!output.canPush()) + return Status::PortFull; + + if (merge_sorter) + { + if (!generated_chunk) + return Status::Ready; + + output.push(std::move(generated_chunk)); + return Status::PortFull; + } + else + { + auto & input = inputs.back(); + + if (input.isFinished()) + { + output.finish(); + return Status::Finished; + } + + input.setNeeded(); + + if (!input.hasData()) + return Status::NeedData; + + auto chunk = input.pull(); + enrichChunkWithConstants(chunk); + output.push(std::move(chunk)); + return Status::PortFull; + } +} + +void MergeSortingTransform::work() +{ + if (stage == Stage::Consume) + consume(std::move(current_chunk)); + + if (stage == Stage::Serialize) + serialize(); + + if (stage == Stage::Generate) + generate(); +} + +Processors MergeSortingTransform::expandPipeline() +{ + if (processors.size() > 1) + { + /// Add external_merging_sorted. + inputs.emplace_back(header_without_constants, this); + connect(external_merging_sorted->getOutputs().front(), inputs.back()); + } + + auto & buffer = processors.front(); + + static_cast(*external_merging_sorted).addInput(); + connect(buffer->getOutputs().back(), external_merging_sorted->getInputs().back()); + + if (!buffer->getInputs().empty()) + { + /// Serialize + outputs.emplace_back(header_without_constants, this); + connect(getOutputs().back(), buffer->getInputs().back()); + /// Hack. Say buffer that we need data from port (otherwise it will return PortFull). + external_merging_sorted->getInputs().back().setNeeded(); + } + else + /// Generate + static_cast(*external_merging_sorted).setHaveAllInputs(); + + return std::move(processors); +} + +void MergeSortingTransform::consume(Chunk chunk) +{ + /** Algorithm: + * - read to memory blocks from source stream; + * - if too many of them and if external sorting is enabled, + * - merge all blocks to sorted stream and write it to temporary file; + * - at the end, merge all sorted streams from temporary files and also from rest of blocks in memory. + */ + + /// If there were only const columns in sort description, then there is no need to sort. + /// Return the chunk as is. + if (description.empty()) + { + generated_chunk = std::move(chunk); + return; + } + + removeConstColumns(chunk); + + sum_rows_in_blocks += chunk.getNumRows(); + sum_bytes_in_blocks += chunk.allocatedBytes(); + chunks.push_back(std::move(chunk)); + + /** If significant amount of data was accumulated, perform preliminary merging step. + */ + if (chunks.size() > 1 + && limit + && limit * 2 < sum_rows_in_blocks /// 2 is just a guess. + && remerge_is_useful + && max_bytes_before_remerge + && sum_bytes_in_blocks > max_bytes_before_remerge) + { + remerge(); + } + + /** If too many of them and if external sorting is enabled, + * will merge blocks that we have in memory at this moment and write merged stream to temporary (compressed) file. + * NOTE. It's possible to check free space in filesystem. + */ + if (max_bytes_before_external_sort && sum_bytes_in_blocks > max_bytes_before_external_sort) + { + Poco::File(tmp_path).createDirectories(); + temporary_files.emplace_back(std::make_unique(tmp_path)); + const std::string & path = temporary_files.back()->path(); + merge_sorter = std::make_unique(std::move(chunks), description, max_merged_block_size, limit); + auto current_processor = std::make_shared(header_without_constants, log, path); + + processors.emplace_back(current_processor); + + if (!external_merging_sorted) + { + bool quiet = false; + bool have_all_inputs = false; + + external_merging_sorted = std::make_shared( + header_without_constants, + 0, + description, + max_merged_block_size, + limit, + quiet, + have_all_inputs); + + processors.emplace_back(external_merging_sorted); + } + + stage = Stage::Serialize; + sum_bytes_in_blocks = 0; + sum_rows_in_blocks = 0; + } +} + +void MergeSortingTransform::serialize() +{ + current_chunk = merge_sorter->read(); + if (!current_chunk) + merge_sorter.reset(); +} + +void MergeSortingTransform::generate() +{ + if (!generated_prefix) + { + if (temporary_files.empty()) + merge_sorter = std::make_unique(std::move(chunks), description, max_merged_block_size, limit); + else + { + ProfileEvents::increment(ProfileEvents::ExternalSortMerge); + LOG_INFO(log, "There are " << temporary_files.size() << " temporary sorted parts to merge."); + + if (!chunks.empty()) + processors.emplace_back(std::make_shared( + header_without_constants, std::move(chunks), description, max_merged_block_size, limit)); + } + + generated_prefix = true; + } + + if (merge_sorter) + { + generated_chunk = merge_sorter->read(); + if (!generated_chunk) + merge_sorter.reset(); + else + enrichChunkWithConstants(generated_chunk); + } +} + +void MergeSortingTransform::remerge() +{ + LOG_DEBUG(log, "Re-merging intermediate ORDER BY data (" << chunks.size() + << " blocks with " << sum_rows_in_blocks << " rows) to save memory consumption"); + + /// NOTE Maybe concat all blocks and partial sort will be faster than merge? + MergeSorter remerge_sorter(std::move(chunks), description, max_merged_block_size, limit); + + Chunks new_chunks; + size_t new_sum_rows_in_blocks = 0; + size_t new_sum_bytes_in_blocks = 0; + + while (auto chunk = remerge_sorter.read()) + { + new_sum_rows_in_blocks += chunk.getNumRows(); + new_sum_bytes_in_blocks += chunk.allocatedBytes(); + new_chunks.emplace_back(std::move(chunk)); + } + + LOG_DEBUG(log, "Memory usage is lowered from " + << formatReadableSizeWithBinarySuffix(sum_bytes_in_blocks) << " to " + << formatReadableSizeWithBinarySuffix(new_sum_bytes_in_blocks)); + + /// If the memory consumption was not lowered enough - we will not perform remerge anymore. 2 is a guess. + if (new_sum_bytes_in_blocks * 2 > sum_bytes_in_blocks) + remerge_is_useful = false; + + chunks = std::move(new_chunks); + sum_rows_in_blocks = new_sum_rows_in_blocks; + sum_bytes_in_blocks = new_sum_bytes_in_blocks; +} + + +void MergeSortingTransform::removeConstColumns(Chunk & chunk) +{ + size_t num_columns = chunk.getNumColumns(); + size_t num_rows = chunk.getNumRows(); + + if (num_columns != const_columns_to_remove.size()) + throw Exception("Block has different number of columns with header: " + toString(num_columns) + + " vs " + toString(const_columns_to_remove.size()), ErrorCodes::LOGICAL_ERROR); + + auto columns = chunk.detachColumns(); + Columns column_without_constants; + column_without_constants.reserve(header_without_constants.columns()); + + for (size_t position = 0; position < num_columns; ++position) + { + if (!const_columns_to_remove[position]) + column_without_constants.push_back(std::move(columns[position])); + } + + chunk.setColumns(std::move(column_without_constants), num_rows); +} + +void MergeSortingTransform::enrichChunkWithConstants(Chunk & chunk) +{ + size_t num_rows = chunk.getNumRows(); + size_t num_result_columns = const_columns_to_remove.size(); + + auto columns = chunk.detachColumns(); + Columns column_with_constants; + column_with_constants.reserve(num_result_columns); + + auto & header = inputs.front().getHeader(); + + size_t next_non_const_column = 0; + for (size_t i = 0; i < num_result_columns; ++i) + { + if (const_columns_to_remove[i]) + column_with_constants.emplace_back(header.getByPosition(i).column->cloneResized(num_rows)); + else + { + if (next_non_const_column >= columns.size()) + throw Exception("Can't enrich chunk with constants because run out of non-constant columns.", + ErrorCodes::LOGICAL_ERROR); + + column_with_constants.emplace_back(std::move(columns[next_non_const_column])); + ++next_non_const_column; + } + } + + chunk.setColumns(std::move(column_with_constants), num_rows); +} + +} diff --git a/dbms/src/Processors/Transforms/MergeSortingTransform.h b/dbms/src/Processors/Transforms/MergeSortingTransform.h new file mode 100644 index 00000000000..0ab517fc5d4 --- /dev/null +++ b/dbms/src/Processors/Transforms/MergeSortingTransform.h @@ -0,0 +1,98 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace DB +{ + +class MergeSorter; + +class MergeSortingTransform : public IProcessor +{ +public: + /// limit - if not 0, allowed to return just first 'limit' rows in sorted order. + MergeSortingTransform(const Block & header, + SortDescription & description_, + size_t max_merged_block_size_, UInt64 limit_, + size_t max_bytes_before_remerge_, + size_t max_bytes_before_external_sort_, const std::string & tmp_path_); + + ~MergeSortingTransform() override; + + String getName() const override { return "MergeSortingTransform"; } + +protected: + + Status prepare() override; + void work() override; + Processors expandPipeline() override; + +private: + SortDescription description; + size_t max_merged_block_size; + UInt64 limit; + + size_t max_bytes_before_remerge; + size_t max_bytes_before_external_sort; + const std::string tmp_path; + + Logger * log = &Logger::get("MergeSortingBlockInputStream"); + + Chunks chunks; + size_t sum_rows_in_blocks = 0; + size_t sum_bytes_in_blocks = 0; + + /// If remerge doesn't save memory at least several times, mark it as useless and don't do it anymore. + bool remerge_is_useful = true; + + /// Before operation, will remove constant columns from blocks. And after, place constant columns back. + /// (to avoid excessive virtual function calls and because constants cannot be serialized in Native format for temporary files) + /// Save original block structure here. + Block header_without_constants; + /// Columns which were constant in header and we need to remove from chunks. + std::vector const_columns_to_remove; + + /// Everything below is for external sorting. + std::vector> temporary_files; + + /// Merge all accumulated blocks to keep no more than limit rows. + void remerge(); + + void removeConstColumns(Chunk & chunk); + void enrichChunkWithConstants(Chunk & chunk); + + enum class Stage + { + Consume = 0, + Generate, + Serialize, + }; + + Stage stage = Stage::Consume; + bool generated_prefix = false; + Chunk current_chunk; + Chunk generated_chunk; + + std::unique_ptr merge_sorter; + ProcessorPtr external_merging_sorted; + Processors processors; + + Status prepareConsume(); + Status prepareSerialize(); + Status prepareGenerate(); + + void consume(Chunk chunk); + void serialize(); + void generate(); +}; + +} diff --git a/dbms/src/Processors/Transforms/MergingAggregatedMemoryEfficientTransform.cpp b/dbms/src/Processors/Transforms/MergingAggregatedMemoryEfficientTransform.cpp new file mode 100644 index 00000000000..a573a6270e9 --- /dev/null +++ b/dbms/src/Processors/Transforms/MergingAggregatedMemoryEfficientTransform.cpp @@ -0,0 +1,519 @@ +#include + +#include +#include +#include + +namespace DB +{ + +struct ChunksToMerge : public ChunkInfo +{ + std::unique_ptr chunks; + Int32 bucket_num = -1; + bool is_overflows = false; +}; + +GroupingAggregatedTransform::GroupingAggregatedTransform( + const Block & header, size_t num_inputs, AggregatingTransformParamsPtr params) + : IProcessor(InputPorts(num_inputs, header), { Block() }) + , num_inputs(num_inputs) + , params(std::move(params)) + , last_bucket_number(num_inputs, -1) + , read_from_input(num_inputs, false) +{ +} + +void GroupingAggregatedTransform::readFromAllInputs() +{ + auto in = inputs.begin(); + for (size_t i = 0; i < num_inputs; ++i, ++in) + { + if (in->isFinished()) + continue; + + if (read_from_input[i]) + continue; + + in->setNeeded(); + + if (!in->hasData()) + return; + + auto chunk = in->pull(); + read_from_input[i] = true; + addChunk(std::move(chunk), i); + } + + read_from_all_inputs = true; +} + +void GroupingAggregatedTransform::pushData(Chunks chunks, Int32 bucket, bool is_overflows) +{ + auto & output = outputs.front(); + + auto info = std::make_shared(); + info->bucket_num = bucket; + info->is_overflows = is_overflows; + info->chunks = std::make_unique(std::move(chunks)); + + Chunk chunk; + chunk.setChunkInfo(std::move(info)); + output.push(std::move(chunk)); +} + +bool GroupingAggregatedTransform::tryPushTwoLevelData() +{ + auto try_push_by_iter = [&](auto batch_it) + { + if (batch_it == chunks_map.end()) + return false; + + Chunks & cur_chunks = batch_it->second; + if (cur_chunks.empty()) + { + chunks_map.erase(batch_it); + return false; + } + + pushData(std::move(cur_chunks), batch_it->first, false); + chunks_map.erase(batch_it); + return true; + }; + + if (all_inputs_finished) + { + /// Chunks are sorted by bucket. + while (!chunks_map.empty()) + if (try_push_by_iter(chunks_map.begin())) + return true; + } + else + { + for (; next_bucket_to_push < current_bucket; ++next_bucket_to_push) + if (try_push_by_iter(chunks_map.find(next_bucket_to_push))) + return true; + } + + return false; +} + +bool GroupingAggregatedTransform::tryPushSingleLevelData() +{ + if (single_level_chunks.empty()) + return false; + + pushData(std::move(single_level_chunks), -1, false); + return true; +} + +bool GroupingAggregatedTransform::tryPushOverflowData() +{ + if (overflow_chunks.empty()) + return false; + + pushData(std::move(overflow_chunks), -1, true); + return true; +} + +IProcessor::Status GroupingAggregatedTransform::prepare() +{ + /// Check can output. + auto & output = outputs.front(); + + if (output.isFinished()) + { + for (auto & input : inputs) + input.close(); + + chunks_map.clear(); + last_bucket_number.clear(); + return Status::Finished; + } + + /// Read first time from each input to understand if we have two-level aggregation. + if (!read_from_all_inputs) + { + readFromAllInputs(); + if (!read_from_all_inputs) + return Status::NeedData; + } + + /// Convert single level to two levels if have two-level input. + if (has_two_level && !single_level_chunks.empty()) + return Status::Ready; + + /// Check can push (to avoid data caching). + if (!output.canPush()) + { + for (auto & input : inputs) + input.setNotNeeded(); + + return Status::PortFull; + } + + bool pushed_to_output = false; + + /// Output if has data. + if (has_two_level) + pushed_to_output = tryPushTwoLevelData(); + + auto need_input = [this](size_t input_num) + { + if (last_bucket_number[input_num] < current_bucket) + return true; + + return expect_several_chunks_for_single_bucket_per_source && last_bucket_number[input_num] == current_bucket; + }; + + /// Read next bucket if can. + for (; ; ++current_bucket) + { + bool finished = true; + bool need_data = false; + + auto in = inputs.begin(); + for (size_t input_num = 0; input_num < num_inputs; ++input_num, ++in) + { + if (in->isFinished()) + continue; + + finished = false; + + if (!need_input(input_num)) + continue; + + in->setNeeded(); + + if (!in->hasData()) + { + need_data = true; + continue; + } + + auto chunk = in->pull(); + addChunk(std::move(chunk), input_num); + + if (has_two_level && !single_level_chunks.empty()) + return Status::Ready; + + if (!in->isFinished() && need_input(input_num)) + need_data = true; + } + + if (finished) + { + all_inputs_finished = true; + break; + } + + if (need_data) + return Status::NeedData; + } + + if (pushed_to_output) + return Status::PortFull; + + if (has_two_level) + { + if (tryPushTwoLevelData()) + return Status::PortFull; + + /// Sanity check. If new bucket was read, we should be able to push it. + if (!all_inputs_finished) + throw Exception("GroupingAggregatedTransform has read new two-level bucket, but couldn't push it.", + ErrorCodes::LOGICAL_ERROR); + } + else + { + if (!all_inputs_finished) + throw Exception("GroupingAggregatedTransform should have read all chunks for single level aggregation, " + "but not all of the inputs are finished.", ErrorCodes::LOGICAL_ERROR); + + if (tryPushSingleLevelData()) + return Status::PortFull; + } + + /// If we haven't pushed to output, then all data was read. Push overflows if have. + if (tryPushOverflowData()) + return Status::PortFull; + + output.finish(); + return Status::Finished; +} + +void GroupingAggregatedTransform::addChunk(Chunk chunk, size_t input) +{ + auto & info = chunk.getChunkInfo(); + if (!info) + throw Exception("Chunk info was not set for chunk in GroupingAggregatedTransform.", ErrorCodes::LOGICAL_ERROR); + + auto * agg_info = typeid_cast(info.get()); + if (!agg_info) + throw Exception("Chunk should have AggregatedChunkInfo in GroupingAggregatedTransform.", ErrorCodes::LOGICAL_ERROR); + + Int32 bucket = agg_info->bucket_num; + bool is_overflows = agg_info->is_overflows; + + if (is_overflows) + overflow_chunks.emplace_back(std::move(chunk)); + else if (bucket < 0) + single_level_chunks.emplace_back(std::move(chunk)); + else + { + chunks_map[bucket].emplace_back(std::move(chunk)); + has_two_level = true; + last_bucket_number[input] = bucket; + } +} + +void GroupingAggregatedTransform::work() +{ + if (!single_level_chunks.empty()) + { + auto & header = getOutputs().front().getHeader(); + auto block = header.cloneWithColumns(single_level_chunks.back().detachColumns()); + single_level_chunks.pop_back(); + auto blocks = params->aggregator.convertBlockToTwoLevel(block); + + for (auto & cur_block : blocks) + { + Int32 bucket = cur_block.info.bucket_num; + chunks_map[bucket].emplace_back(Chunk(cur_block.getColumns(), cur_block.rows())); + } + } +} + + +MergingAggregatedBucketTransform::MergingAggregatedBucketTransform(AggregatingTransformParamsPtr params) + : ISimpleTransform({}, params->getHeader(), false), params(std::move(params)) +{ + setInputNotNeededAfterRead(true); +} + +void MergingAggregatedBucketTransform::transform(Chunk & chunk) +{ + auto & info = chunk.getChunkInfo(); + auto * chunks_to_merge = typeid_cast(info.get()); + + if (!chunks_to_merge) + throw Exception("MergingAggregatedSimpleTransform chunk must have ChunkInfo with type ChunksToMerge.", + ErrorCodes::LOGICAL_ERROR); + + auto header = params->aggregator.getHeader(false); + + BlocksList blocks_list; + for (auto & cur_chunk : *chunks_to_merge->chunks) + { + auto & cur_info = cur_chunk.getChunkInfo(); + if (!cur_info) + throw Exception("Chunk info was not set for chunk in MergingAggregatedBucketTransform.", + ErrorCodes::LOGICAL_ERROR); + + auto * agg_info = typeid_cast(cur_info.get()); + if (!agg_info) + throw Exception("Chunk should have AggregatedChunkInfo in MergingAggregatedBucketTransform.", + ErrorCodes::LOGICAL_ERROR); + + Block block = header.cloneWithColumns(cur_chunk.detachColumns()); + block.info.is_overflows = agg_info->is_overflows; + block.info.bucket_num = agg_info->bucket_num; + + blocks_list.emplace_back(std::move(block)); + } + + auto res_info = std::make_shared(); + res_info->is_overflows = chunks_to_merge->is_overflows; + res_info->bucket_num = chunks_to_merge->bucket_num; + chunk.setChunkInfo(std::move(res_info)); + + auto block = params->aggregator.mergeBlocks(blocks_list, params->final); + size_t num_rows = block.rows(); + chunk.setColumns(block.getColumns(), num_rows); +} + + +SortingAggregatedTransform::SortingAggregatedTransform(size_t num_inputs, AggregatingTransformParamsPtr params) + : IProcessor(InputPorts(num_inputs, params->getHeader()), {params->getHeader()}) + , num_inputs(num_inputs) + , params(std::move(params)) + , last_bucket_number(num_inputs, -1) + , is_input_finished(num_inputs, false) +{ +} + +bool SortingAggregatedTransform::tryPushChunk() +{ + auto & output = outputs.front(); + + if (chunks.empty()) + return false; + + /// Chunk with min current bucket. + auto it = chunks.begin(); + auto cur_bucket = it->first; + + /// Check that can push it + for (size_t input = 0; input < num_inputs; ++input) + if (!is_input_finished[input] && last_bucket_number[input] < cur_bucket) + return false; + + output.push(std::move(it->second)); + chunks.erase(it); + return true; +} + +void SortingAggregatedTransform::addChunk(Chunk chunk, size_t from_input) +{ + auto & info = chunk.getChunkInfo(); + if (!info) + throw Exception("Chunk info was not set for chunk in SortingAggregatedTransform.", ErrorCodes::LOGICAL_ERROR); + + auto * agg_info = typeid_cast(info.get()); + if (!agg_info) + throw Exception("Chunk should have AggregatedChunkInfo in SortingAggregatedTransform.", ErrorCodes::LOGICAL_ERROR); + + Int32 bucket = agg_info->bucket_num; + bool is_overflows = agg_info->is_overflows; + + if (is_overflows) + overflow_chunk = std::move(chunk); + else + { + if (chunks[bucket]) + throw Exception("SortingAggregatedTransform already got bucket with number " + toString(bucket), + ErrorCodes::LOGICAL_ERROR); + + chunks[bucket] = std::move(chunk); + last_bucket_number[from_input] = bucket; + } +} + +IProcessor::Status SortingAggregatedTransform::prepare() +{ + /// Check can output. + auto & output = outputs.front(); + + if (output.isFinished()) + { + for (auto & input : inputs) + input.close(); + + chunks.clear(); + last_bucket_number.clear(); + return Status::Finished; + } + + /// Check can push (to avoid data caching). + if (!output.canPush()) + { + for (auto & input : inputs) + input.setNotNeeded(); + + return Status::PortFull; + } + + /// Push if have min version. + bool pushed_to_output = tryPushChunk(); + + bool need_data = false; + bool all_finished = true; + + /// Try read anything. + auto in = inputs.begin(); + for (size_t input_num = 0; input_num < num_inputs; ++input_num, ++in) + { + if (in->isFinished()) + { + is_input_finished[input_num] = true; + continue; + } + + all_finished = false; + + in->setNeeded(); + + if (!in->hasData()) + { + need_data = true; + continue; + } + + auto chunk = in->pull(); + /// If chunk was pulled, then we need data from this port. + need_data = true; + + addChunk(std::move(chunk), input_num); + } + + if (pushed_to_output) + return Status::PortFull; + + if (tryPushChunk()) + return Status::PortFull; + + if (need_data) + return Status::NeedData; + + if (!all_finished) + throw Exception("SortingAggregatedTransform has read bucket, but couldn't push it.", + ErrorCodes::LOGICAL_ERROR); + + if (overflow_chunk) + { + output.push(std::move(overflow_chunk)); + return Status::PortFull; + } + + output.finish(); + return Status::Finished; +} + + +Processors createMergingAggregatedMemoryEfficientPipe( + Block header, + AggregatingTransformParamsPtr params, + size_t num_inputs, + size_t num_merging_processors) +{ + Processors processors; + processors.reserve(num_merging_processors + 2); + + auto grouping = std::make_shared(header, num_inputs, params); + processors.emplace_back(std::move(grouping)); + + if (num_merging_processors <= 1) + { + /// --> GroupingAggregated --> MergingAggregatedBucket --> + auto transform = std::make_shared(params); + connect(processors.back()->getOutputs().front(), transform->getInputPort()); + + processors.emplace_back(std::move(transform)); + return processors; + } + + /// --> --> MergingAggregatedBucket --> + /// --> GroupingAggregated --> ResizeProcessor --> MergingAggregatedBucket --> SortingAggregated --> + /// --> --> MergingAggregatedBucket --> + + auto resize = std::make_shared(Block(), 1, num_merging_processors); + connect(processors.back()->getOutputs().front(), resize->getInputs().front()); + processors.emplace_back(std::move(resize)); + + auto sorting = std::make_shared(num_merging_processors, params); + auto out = processors.back()->getOutputs().begin(); + auto in = sorting->getInputs().begin(); + + for (size_t i = 0; i < num_merging_processors; ++i, ++in, ++out) + { + auto transform = std::make_shared(params); + connect(*out, transform->getInputPort()); + connect(transform->getOutputPort(), *in); + processors.emplace_back(std::move(transform)); + } + + processors.emplace_back(std::move(sorting)); + return processors; +} + +} diff --git a/dbms/src/Processors/Transforms/MergingAggregatedMemoryEfficientTransform.h b/dbms/src/Processors/Transforms/MergingAggregatedMemoryEfficientTransform.h new file mode 100644 index 00000000000..eff71e954a9 --- /dev/null +++ b/dbms/src/Processors/Transforms/MergingAggregatedMemoryEfficientTransform.h @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include + + +namespace DB +{ + +/// Has several inputs and single output. +/// Read from inputs chunks with partially aggregated data, group them by bucket number +/// and write data from single bucket as single chunk. +class GroupingAggregatedTransform : public IProcessor +{ +public: + GroupingAggregatedTransform(const Block & header, size_t num_inputs, AggregatingTransformParamsPtr params); + String getName() const override { return "GroupingAggregatedTransform"; } + + /// Special setting: in case if single source can return several chunks with same bucket. + void allowSeveralChunksForSingleBucketPerSource() { expect_several_chunks_for_single_bucket_per_source = true; } + +protected: + Status prepare() override; + void work() override; + +private: + size_t num_inputs; + AggregatingTransformParamsPtr params; + + std::vector last_bucket_number; + std::map chunks_map; + Chunks overflow_chunks; + Chunks single_level_chunks; + Int32 current_bucket = 0; + Int32 next_bucket_to_push = 0; /// Always <= current_bucket. + bool has_two_level = false; + + bool all_inputs_finished = false; + bool read_from_all_inputs = false; + std::vector read_from_input; + + bool expect_several_chunks_for_single_bucket_per_source = false; + + void addChunk(Chunk chunk, size_t input); + void readFromAllInputs(); + bool tryPushSingleLevelData(); + bool tryPushTwoLevelData(); + bool tryPushOverflowData(); + void pushData(Chunks chunks, Int32 bucket, bool is_overflows); +}; + +/// Merge aggregated data from single bucket. +class MergingAggregatedBucketTransform : public ISimpleTransform +{ +public: + explicit MergingAggregatedBucketTransform(AggregatingTransformParamsPtr params); + String getName() const override { return "MergingAggregatedBucketTransform"; } + +protected: + void transform(Chunk & chunk) override; + +private: + AggregatingTransformParamsPtr params; +}; + +/// Has several inputs and single output. +/// Read from inputs merged bucket with aggregated data, sort them by bucket number and write to output. +/// Presumption: inputs return chunks with increasing bucket number, there is at most one chunk per bucket. +class SortingAggregatedTransform : public IProcessor +{ +public: + SortingAggregatedTransform(size_t num_inputs, AggregatingTransformParamsPtr params); + String getName() const override { return "SortingAggregatedTransform"; } + Status prepare() override; + +private: + size_t num_inputs; + AggregatingTransformParamsPtr params; + std::vector last_bucket_number; + std::vector is_input_finished; + std::map chunks; + Chunk overflow_chunk; + + bool tryPushChunk(); + void addChunk(Chunk chunk, size_t from_input); +}; + +/// Creates piece of pipeline which performs memory efficient merging of partially aggregated data from several sources. +/// First processor will have num_inputs, last - single output. You should connect them to create pipeline. +Processors createMergingAggregatedMemoryEfficientPipe( + Block header, + AggregatingTransformParamsPtr params, + size_t num_inputs, + size_t num_merging_processors); + +} + diff --git a/dbms/src/Processors/Transforms/MergingAggregatedTransform.cpp b/dbms/src/Processors/Transforms/MergingAggregatedTransform.cpp new file mode 100644 index 00000000000..32b833044cd --- /dev/null +++ b/dbms/src/Processors/Transforms/MergingAggregatedTransform.cpp @@ -0,0 +1,74 @@ +#include +#include + +namespace DB +{ + +MergingAggregatedTransform::MergingAggregatedTransform( + Block header, AggregatingTransformParamsPtr params, size_t max_threads) + : IAccumulatingTransform(std::move(header), params->getHeader()) + , params(std::move(params)), max_threads(max_threads) +{ +} + +void MergingAggregatedTransform::consume(Chunk chunk) +{ + if (!consume_started) + { + consume_started = true; + LOG_TRACE(log, "Reading blocks of partially aggregated data."); + } + + total_input_rows += chunk.getNumRows(); + ++total_input_blocks; + + auto & info = chunk.getChunkInfo(); + if (!info) + throw Exception("Chunk info was not set for chunk in MergingAggregatedTransform.", ErrorCodes::LOGICAL_ERROR); + + auto * agg_info = typeid_cast(info.get()); + if (!agg_info) + throw Exception("Chunk should have AggregatedChunkInfo in MergingAggregatedTransform.", ErrorCodes::LOGICAL_ERROR); + + auto block = getInputPort().getHeader().cloneWithColumns(chunk.getColumns()); + block.info.is_overflows = agg_info->is_overflows; + block.info.bucket_num = agg_info->bucket_num; + + bucket_to_blocks[agg_info->bucket_num].emplace_back(std::move(block)); +} + +Chunk MergingAggregatedTransform::generate() +{ + if (!generate_started) + { + generate_started = true; + LOG_TRACE(log, "Read " << total_input_blocks << " blocks of partially aggregated data, total " << total_input_rows + << " rows."); + + /// Exception safety. Make iterator valid in case any method below throws. + next_block = blocks.begin(); + + /// TODO: this operation can be made async. Add async for IAccumulatingTransform. + params->aggregator.mergeBlocks(std::move(bucket_to_blocks), data_variants, max_threads); + blocks = params->aggregator.convertToBlocks(data_variants, params->final, max_threads); + next_block = blocks.begin(); + } + + if (next_block == blocks.end()) + return {}; + + auto block = std::move(*next_block); + ++next_block; + + auto info = std::make_shared(); + info->bucket_num = block.info.bucket_num; + info->is_overflows = block.info.is_overflows; + + UInt64 num_rows = block.rows(); + Chunk chunk(block.getColumns(), num_rows); + chunk.setChunkInfo(std::move(info)); + + return chunk; +} + +} diff --git a/dbms/src/Processors/Transforms/MergingAggregatedTransform.h b/dbms/src/Processors/Transforms/MergingAggregatedTransform.h new file mode 100644 index 00000000000..a8c52f2b047 --- /dev/null +++ b/dbms/src/Processors/Transforms/MergingAggregatedTransform.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include +#include + +namespace DB +{ + +/** A pre-aggregate stream of blocks in which each block is already aggregated. + * Aggregate functions in blocks should not be finalized so that their states can be merged. + */ +class MergingAggregatedTransform : public IAccumulatingTransform +{ +public: + MergingAggregatedTransform(Block header, AggregatingTransformParamsPtr params, size_t max_threads); + String getName() const override { return "MergingAggregatedTransform"; } + +protected: + void consume(Chunk chunk) override; + Chunk generate() override; + +private: + AggregatingTransformParamsPtr params; + Logger * log = &Logger::get("MergingAggregatedTransform"); + size_t max_threads; + + AggregatedDataVariants data_variants; + Aggregator::BucketToBlocks bucket_to_blocks; + + UInt64 total_input_rows = 0; + UInt64 total_input_blocks = 0; + + BlocksList blocks; + BlocksList::iterator next_block; + + bool consume_started = false; + bool generate_started = false; +}; + +} diff --git a/dbms/src/Processors/Transforms/MergingSortedTransform.cpp b/dbms/src/Processors/Transforms/MergingSortedTransform.cpp new file mode 100644 index 00000000000..b0283b0a56e --- /dev/null +++ b/dbms/src/Processors/Transforms/MergingSortedTransform.cpp @@ -0,0 +1,330 @@ +#include +#include +#include + +namespace DB +{ + +MergingSortedTransform::MergingSortedTransform( + const Block & header, + size_t num_inputs, + const SortDescription & description_, + size_t max_block_size, + UInt64 limit, + bool quiet, + bool have_all_inputs) + : IProcessor(InputPorts(num_inputs, header), {header}) + , description(description_), max_block_size(max_block_size), limit(limit), quiet(quiet) + , have_all_inputs(have_all_inputs) + , merged_data(header), source_chunks(num_inputs), cursors(num_inputs) +{ + auto & sample = outputs.front().getHeader(); + /// Replace column names in description to positions. + for (auto & column_description : description) + { + has_collation |= column_description.collator != nullptr; + if (!column_description.column_name.empty()) + { + column_description.column_number = sample.getPositionByName(column_description.column_name); + column_description.column_name.clear(); + } + } +} + +void MergingSortedTransform::addInput() +{ + if (have_all_inputs) + throw Exception("MergingSortedTransform already have all inputs.", ErrorCodes::LOGICAL_ERROR); + + inputs.emplace_back(outputs.front().getHeader(), this); + source_chunks.emplace_back(); + cursors.emplace_back(); +} + +void MergingSortedTransform::setHaveAllInputs() +{ + if (have_all_inputs) + throw Exception("MergingSortedTransform already have all inputs.", ErrorCodes::LOGICAL_ERROR); + + have_all_inputs = true; +} + +IProcessor::Status MergingSortedTransform::prepare() +{ + if (!have_all_inputs) + return Status::NeedData; + + auto & output = outputs.front(); + + /// Special case for no inputs. + if (inputs.empty()) + { + output.finish(); + return Status::Finished; + } + + /// Check can output. + + if (output.isFinished()) + { + for (auto & in : inputs) + in.close(); + + return Status::Finished; + } + + if (!output.isNeeded()) + { + for (auto & in : inputs) + in.setNotNeeded(); + + return Status::PortFull; + } + + if (output.hasData()) + return Status::PortFull; + + /// Special case for single input. + if (inputs.size() == 1) + { + auto & input = inputs.front(); + if (input.isFinished()) + { + output.finish(); + return Status::Finished; + } + + input.setNeeded(); + if (input.hasData()) + output.push(input.pull()); + + return Status::NeedData; + } + + /// Push if has data. + if (merged_data.mergedRows()) + output.push(merged_data.pull()); + + if (!is_initialized) + { + /// Check for inputs we need. + bool all_inputs_has_data = true; + auto it = inputs.begin(); + for (size_t i = 0; it != inputs.end(); ++i, ++it) + { + auto & input = *it; + if (input.isFinished()) + continue; + + if (!cursors[i].empty()) + { + input.setNotNeeded(); + continue; + } + + input.setNeeded(); + + if (!input.hasData()) + { + all_inputs_has_data = false; + continue; + } + + auto chunk = input.pull(); + if (chunk.hasNoRows()) + { + all_inputs_has_data = false; + continue; + } + + updateCursor(std::move(chunk), i); + } + + if (!all_inputs_has_data) + return Status::NeedData; + + if (has_collation) + initQueue(queue_with_collation); + else + initQueue(queue_without_collation); + + is_initialized = true; + return Status::Ready; + } + else + { + if (is_finished) + { + for (auto & input : inputs) + input.close(); + + outputs.front().finish(); + + return Status::Finished; + } + + if (need_data) + { + + auto & input = *std::next(inputs.begin(), next_input_to_read); + if (!input.isFinished()) + { + input.setNeeded(); + + if (!input.hasData()) + return Status::NeedData; + + auto chunk = input.pull(); + if (chunk.hasNoRows()) + return Status::NeedData; + + updateCursor(std::move(chunk), next_input_to_read); + pushToQueue(next_input_to_read); + need_data = false; + } + } + + return Status::Ready; + } +} + +void MergingSortedTransform::work() +{ + if (has_collation) + merge(queue_with_collation); + else + merge(queue_without_collation); +} + +template +void MergingSortedTransform::merge(std::priority_queue & queue) +{ + /// Returns MergeStatus which we should return if we are going to finish now. + auto can_read_another_row = [&, this]() + { + if (limit && merged_data.totalMergedRows() >= limit) + { + //std::cerr << "Limit reached\n"; + is_finished = true; + return false; + } + + if (merged_data.mergedRows() >= max_block_size) + { + //std::cerr << "max_block_size reached\n"; + return false; + } + + return true; + }; + + /// Take rows in required order and put them into `merged_data`, while the rows are no more than `max_block_size` + while (!queue.empty()) + { + /// Shouldn't happen at first iteration, but check just in case. + if (!can_read_another_row()) + return; + + TSortCursor current = queue.top(); + queue.pop(); + bool first_iteration = true; + + while (true) + { + if (!first_iteration && !can_read_another_row()) + { + queue.push(current); + return; + } + first_iteration = false; + + /** And what if the block is totally less or equal than the rest for the current cursor? + * Or is there only one data source left in the queue? Then you can take the entire block on current cursor. + */ + if (current.impl->isFirst() && (queue.empty() || current.totallyLessOrEquals(queue.top()))) + { + //std::cerr << "current block is totally less or equals\n"; + + /// If there are already data in the current block, we first return it. We'll get here again the next time we call the merge function. + if (merged_data.mergedRows() != 0) + { + //std::cerr << "merged rows is non-zero\n"; + queue.push(current); + return; + } + + /// Actually, current.impl->order stores source number (i.e. cursors[current.impl->order] == current.impl) + size_t source_num = current.impl->order; + insertFromChunk(source_num); + return; + } + + //std::cerr << "total_merged_rows: " << total_merged_rows << ", merged_rows: " << merged_rows << "\n"; + //std::cerr << "Inserting row\n"; + merged_data.insertRow(current->all_columns, current->pos); + + if (out_row_sources_buf) + { + /// Actually, current.impl->order stores source number (i.e. cursors[current.impl->order] == current.impl) + RowSourcePart row_source(current.impl->order); + out_row_sources_buf->write(row_source.data); + } + + if (current->isLast()) + { + need_data = true; + next_input_to_read = current.impl->order; + + if (limit && merged_data.totalMergedRows() >= limit) + is_finished = true; + + return; + } + + //std::cerr << "moving to next row\n"; + current->next(); + + if (!queue.empty() && current.greater(queue.top())) + { + //std::cerr << "next row is not least, pushing back to queue\n"; + queue.push(current); + break; + } + } + } + is_finished = true; +} + +void MergingSortedTransform::insertFromChunk(size_t source_num) +{ + if (source_num >= cursors.size()) + throw Exception("Logical error in MergingSortedTrandform", ErrorCodes::LOGICAL_ERROR); + + //std::cerr << "copied columns\n"; + + auto num_rows = source_chunks[source_num]->getNumRows(); + + UInt64 total_merged_rows_after_insertion = merged_data.mergedRows() + num_rows; + if (limit && total_merged_rows_after_insertion > limit) + { + num_rows = total_merged_rows_after_insertion - limit; + merged_data.insertFromChunk(std::move(*source_chunks[source_num]), num_rows); + is_finished = true; + } + else + { + merged_data.insertFromChunk(std::move(*source_chunks[source_num]), 0); + need_data = true; + next_input_to_read = source_num; + } + + if (out_row_sources_buf) + { + RowSourcePart row_source(source_num); + for (size_t i = 0; i < num_rows; ++i) + out_row_sources_buf->write(row_source.data); + } +} + + +} diff --git a/dbms/src/Processors/Transforms/MergingSortedTransform.h b/dbms/src/Processors/Transforms/MergingSortedTransform.h new file mode 100644 index 00000000000..5a1f417fdb6 --- /dev/null +++ b/dbms/src/Processors/Transforms/MergingSortedTransform.h @@ -0,0 +1,203 @@ +#pragma once +#include +#include +#include + +#include + +namespace DB +{ + +/// Allows you refer to the row in the block and hold the block ownership, +/// and thus avoid creating a temporary row object. +/// Do not use std::shared_ptr, since there is no need for a place for `weak_count` and `deleter`; +/// does not use Poco::SharedPtr, since you need to allocate a block and `refcount` in one piece; +/// does not use Poco::AutoPtr, since it does not have a `move` constructor and there are extra checks for nullptr; +/// The reference counter is not atomic, since it is used from one thread. +namespace detail +{ +struct SharedChunk : Chunk +{ + int refcount = 0; + + ColumnRawPtrs all_columns; + ColumnRawPtrs sort_columns; + + SharedChunk(Chunk && chunk) : Chunk(std::move(chunk)) {} +}; + +} + +using SharedChunkPtr = boost::intrusive_ptr; + + +inline void intrusive_ptr_add_ref(detail::SharedChunk * ptr) +{ + ++ptr->refcount; +} + +inline void intrusive_ptr_release(detail::SharedChunk * ptr) +{ + if (0 == --ptr->refcount) + delete ptr; +} + +class MergingSortedTransform : public IProcessor +{ +public: + MergingSortedTransform( + const Block & header, + size_t num_inputs, + const SortDescription & description_, + size_t max_block_size, + UInt64 limit = 0, + bool quiet = false, + bool have_all_inputs = true); + + String getName() const override { return "MergingSortedTransform"; } + Status prepare() override; + void work() override; + + void addInput(); + void setHaveAllInputs(); + +protected: + + class MergedData + { + public: + explicit MergedData(const Block & header) + { + columns.reserve(header.columns()); + for (const auto & column : header) + columns.emplace_back(column.type->createColumn()); + } + + void insertRow(const ColumnRawPtrs & raw_columns, size_t row) + { + size_t num_columns = raw_columns.size(); + for (size_t i = 0; i < num_columns; ++i) + columns[i]->insertFrom(*raw_columns[i], row); + + ++total_merged_rows; + ++merged_rows; + } + + void insertFromChunk(Chunk && chunk, size_t limit_rows) + { + if (merged_rows) + throw Exception("Cannot insert to MergedData from Chunk because MergedData is not empty.", + ErrorCodes::LOGICAL_ERROR); + + auto num_rows = chunk.getNumRows(); + columns = chunk.mutateColumns(); + if (limit_rows && num_rows > limit_rows) + for (auto & column : columns) + column = (*column->cut(0, limit_rows)).mutate(); + + total_merged_rows += num_rows; + merged_rows = num_rows; + } + + Chunk pull() + { + MutableColumns empty_columns; + empty_columns.reserve(columns.size()); + + for (const auto & column : columns) + empty_columns.emplace_back(column->cloneEmpty()); + + empty_columns.swap(columns); + Chunk chunk(std::move(empty_columns), merged_rows); + merged_rows = 0; + + return chunk; + } + + UInt64 totalMergedRows() const { return total_merged_rows; } + UInt64 mergedRows() const { return merged_rows; } + + private: + UInt64 total_merged_rows = 0; + UInt64 merged_rows = 0; + MutableColumns columns; + }; + + /// Settings + SortDescription description; + const size_t max_block_size; + UInt64 limit; + bool has_collation = false; + bool quiet = false; + + std::atomic have_all_inputs; + + MergedData merged_data; + + /// Used in Vertical merge algorithm to gather non-PK/non-index columns (on next step) + /// If it is not nullptr then it should be populated during execution + WriteBuffer * out_row_sources_buf = nullptr; + + /// Chunks currently being merged. + std::vector source_chunks; + + using CursorImpls = std::vector; + CursorImpls cursors; + + using Queue = std::priority_queue; + Queue queue_without_collation; + + using QueueWithCollation = std::priority_queue; + QueueWithCollation queue_with_collation; + +private: + + /// Processor state. + bool is_initialized = false; + bool is_finished = false; + bool need_data = false; + size_t next_input_to_read = 0; + + template + void merge(std::priority_queue & queue); + + void insertFromChunk(size_t source_num); + + void updateCursor(Chunk chunk, size_t source_num) + { + auto & shared_chunk_ptr = source_chunks[source_num]; + + if (!shared_chunk_ptr) + { + shared_chunk_ptr = new detail::SharedChunk(std::move(chunk)); + cursors[source_num] = SortCursorImpl(shared_chunk_ptr->getColumns(), description, source_num); + has_collation |= cursors[source_num].has_collation; + } + else + { + *shared_chunk_ptr = std::move(chunk); + cursors[source_num].reset(shared_chunk_ptr->getColumns(), {}); + } + + shared_chunk_ptr->all_columns = cursors[source_num].all_columns; + shared_chunk_ptr->sort_columns = cursors[source_num].sort_columns; + } + + void pushToQueue(size_t source_num) + { + if (has_collation) + queue_with_collation.push(SortCursorWithCollation(&cursors[source_num])); + else + queue_without_collation.push(SortCursor(&cursors[source_num])); + } + + template + void initQueue(std::priority_queue & queue) + { + for (auto & cursor : cursors) + if (!cursor.empty()) + queue.push(TSortCursor(&cursor)); + } +}; + +} diff --git a/dbms/src/Processors/Transforms/PartialSortingTransform.cpp b/dbms/src/Processors/Transforms/PartialSortingTransform.cpp new file mode 100644 index 00000000000..0f15c34c7ff --- /dev/null +++ b/dbms/src/Processors/Transforms/PartialSortingTransform.cpp @@ -0,0 +1,26 @@ +#include +#include + +namespace DB +{ + +PartialSortingTransform::PartialSortingTransform( + const Block & header, SortDescription & description, UInt64 limit, bool do_count_rows) + : ISimpleTransform(header, header, false) + , description(description), limit(limit), do_count_rows(do_count_rows) +{ +} + +void PartialSortingTransform::transform(Chunk & chunk) +{ + if (do_count_rows) + read_rows += chunk.getNumRows(); + + auto block = getInputPort().getHeader().cloneWithColumns(chunk.detachColumns()); + chunk.clear(); + + sortBlock(block, description, limit); + chunk.setColumns(block.getColumns(), block.rows()); +} + +} diff --git a/dbms/src/Processors/Transforms/PartialSortingTransform.h b/dbms/src/Processors/Transforms/PartialSortingTransform.h new file mode 100644 index 00000000000..645b4ebab07 --- /dev/null +++ b/dbms/src/Processors/Transforms/PartialSortingTransform.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include + +namespace DB +{ + +/** Sorts each block individually by the values of the specified columns. + * At the moment, not very optimal algorithm is used. + */ +class PartialSortingTransform : public ISimpleTransform +{ +public: + /// limit - if not 0, then you can sort each block not completely, but only `limit` first rows by order. + /// When count_rows is false, getNumReadRows() will always return 0. + PartialSortingTransform( + const Block & header, + SortDescription & description, + UInt64 limit = 0, + bool do_count_rows = true); + + String getName() const override { return "PartialSortingTransform"; } + + /// Total num rows passed to transform. + UInt64 getNumReadRows() const { return read_rows; } + +protected: + void transform(Chunk & chunk) override; + +private: + SortDescription description; + UInt64 limit; + UInt64 read_rows = 0; + + /// Do we need calculate read_rows value? + /// Used to skip total row when count rows_before_limit_at_least. + bool do_count_rows; +}; + +} diff --git a/dbms/src/Processors/Transforms/RollupTransform.cpp b/dbms/src/Processors/Transforms/RollupTransform.cpp new file mode 100644 index 00000000000..9c8270ce091 --- /dev/null +++ b/dbms/src/Processors/Transforms/RollupTransform.cpp @@ -0,0 +1,49 @@ +#include +#include + +namespace DB +{ + +RollupTransform::RollupTransform(Block header, AggregatingTransformParamsPtr params_) + : IInflatingTransform(std::move(header), params_->getHeader()) + , params(std::move(params_)) + , keys(params->params.keys) +{ +} + +void RollupTransform::consume(Chunk chunk) +{ + consumed_chunk = std::move(chunk); + last_removed_key = keys.size(); +} + +bool RollupTransform::canGenerate() +{ + return consumed_chunk; +} + +Chunk RollupTransform::generate() +{ + auto gen_chunk = std::move(consumed_chunk); + + if (last_removed_key) + { + --last_removed_key; + auto key = keys[last_removed_key]; + + auto num_rows = gen_chunk.getNumRows(); + auto columns = gen_chunk.getColumns(); + columns[key] = columns[key]->cloneEmpty()->cloneResized(num_rows); + + BlocksList rollup_blocks = { getInputPort().getHeader().cloneWithColumns(columns) }; + auto rollup_block = params->aggregator.mergeBlocks(rollup_blocks, false); + + num_rows = rollup_block.rows(); + consumed_chunk = Chunk(rollup_block.getColumns(), num_rows); + } + + finalizeChunk(gen_chunk); + return gen_chunk; +} + +} diff --git a/dbms/src/Processors/Transforms/RollupTransform.h b/dbms/src/Processors/Transforms/RollupTransform.h new file mode 100644 index 00000000000..754e0237357 --- /dev/null +++ b/dbms/src/Processors/Transforms/RollupTransform.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include + +namespace DB +{ + +/// Takes blocks after grouping, with non-finalized aggregate functions. +/// Calculates subtotals and grand totals values for a set of columns. +class RollupTransform : public IInflatingTransform +{ +public: + RollupTransform(Block header, AggregatingTransformParamsPtr params); + String getName() const override { return "RollupTransform"; } + +protected: + void consume(Chunk chunk) override; + bool canGenerate() override; + Chunk generate() override; + +private: + AggregatingTransformParamsPtr params; + ColumnNumbers keys; + Chunk consumed_chunk; + size_t last_removed_key = 0; +}; + +} diff --git a/dbms/src/Processors/Transforms/TotalsHavingTransform.cpp b/dbms/src/Processors/Transforms/TotalsHavingTransform.cpp new file mode 100644 index 00000000000..9b716aca03c --- /dev/null +++ b/dbms/src/Processors/Transforms/TotalsHavingTransform.cpp @@ -0,0 +1,276 @@ +#include +#include + +#include +#include + +#include +#include +#include + +namespace DB +{ + +void finalizeChunk(Chunk & chunk) +{ + auto num_rows = chunk.getNumRows(); + auto columns = chunk.detachColumns(); + + for (auto & column : columns) + if (auto * agg_function = typeid_cast(column.get())) + column = agg_function->convertToValues(); + + chunk.setColumns(std::move(columns), num_rows); +} + +static Block createOutputHeader(Block block, const ExpressionActionsPtr & expression, bool final) +{ + if (final) + finalizeBlock(block); + + if (expression) + expression->execute(block); + + return block; +} + +TotalsHavingTransform::TotalsHavingTransform( + const Block & header, + bool overflow_row_, + const ExpressionActionsPtr & expression_, + const std::string & filter_column_, + TotalsMode totals_mode_, + double auto_include_threshold_, + bool final_) + : ISimpleTransform(header, createOutputHeader(header, expression_, final_), true) + , overflow_row(overflow_row_) + , expression(expression_) + , filter_column_name(filter_column_) + , totals_mode(totals_mode_) + , auto_include_threshold(auto_include_threshold_) + , final(final_) + , arena(std::make_shared()) +{ + if (!filter_column_name.empty()) + filter_column_pos = outputs.front().getHeader().getPositionByName(filter_column_name); + + finalized_header = getInputPort().getHeader(); + finalizeBlock(finalized_header); + + /// Port for Totals. + if (expression) + { + auto totals_header = finalized_header; + expression->execute(totals_header); + outputs.emplace_back(totals_header, this); + } + else + outputs.emplace_back(finalized_header, this); + + /// Initialize current totals with initial state. + current_totals.reserve(header.columns()); + for (const auto & elem : header) + { + if (const auto * column = typeid_cast(elem.column.get())) + { + /// Create ColumnAggregateFunction with initial aggregate function state. + + IAggregateFunction * function = column->getAggregateFunction().get(); + auto target = ColumnAggregateFunction::create(column->getAggregateFunction(), Arenas(1, arena)); + AggregateDataPtr data = arena->alignedAlloc(function->sizeOfData(), function->alignOfData()); + function->create(data); + target->getData().push_back(data); + current_totals.emplace_back(std::move(target)); + } + else + { + /// Not an aggregate function state. Just create a column with default value. + + MutableColumnPtr new_column = elem.type->createColumn(); + elem.type->insertDefaultInto(*new_column); + current_totals.emplace_back(std::move(new_column)); + } + } +} + +IProcessor::Status TotalsHavingTransform::prepare() +{ + if (!finished_transform) + { + auto status = ISimpleTransform::prepare(); + + if (status != Status::Finished) + return status; + + finished_transform = true; + } + + auto & totals_output = getTotalsPort(); + + /// Check can output. + if (totals_output.isFinished()) + return Status::Finished; + + if (!totals_output.canPush()) + return Status::PortFull; + + if (!totals) + return Status::Ready; + + totals_output.push(std::move(totals)); + totals_output.finish(); + return Status::Finished; +} + +void TotalsHavingTransform::work() +{ + if (finished_transform) + prepareTotals(); + else + ISimpleTransform::work(); +} + +void TotalsHavingTransform::transform(Chunk & chunk) +{ + /// Block with values not included in `max_rows_to_group_by`. We'll postpone it. + if (overflow_row) + { + auto & info = chunk.getChunkInfo(); + if (!info) + throw Exception("Chunk info was not set for chunk in TotalsHavingTransform.", ErrorCodes::LOGICAL_ERROR); + + auto * agg_info = typeid_cast(info.get()); + if (!agg_info) + throw Exception("Chunk should have AggregatedChunkInfo in TotalsHavingTransform.", ErrorCodes::LOGICAL_ERROR); + + if (agg_info->is_overflows) + { + overflow_aggregates = std::move(chunk); + return; + } + } + + if (!chunk) + return; + + auto finalized = chunk.clone(); + if (final) + finalizeChunk(finalized); + + total_keys += finalized.getNumRows(); + + if (filter_column_name.empty()) + { + addToTotals(chunk, nullptr); + chunk = std::move(finalized); + } + else + { + /// Compute the expression in HAVING. + auto & cur_header = final ? finalized_header : getInputPort().getHeader(); + auto finalized_block = cur_header.cloneWithColumns(finalized.detachColumns()); + expression->execute(finalized_block); + auto columns = finalized_block.getColumns(); + + ColumnPtr filter_column_ptr = columns[filter_column_pos]; + ConstantFilterDescription const_filter_description(*filter_column_ptr); + + if (const_filter_description.always_true) + { + addToTotals(chunk, nullptr); + return; + } + + if (const_filter_description.always_false) + { + if (totals_mode == TotalsMode::BEFORE_HAVING) + addToTotals(chunk, nullptr); + + chunk.clear(); + return; + } + + FilterDescription filter_description(*filter_column_ptr); + + /// Add values to `totals` (if it was not already done). + if (totals_mode == TotalsMode::BEFORE_HAVING) + addToTotals(chunk, nullptr); + else + addToTotals(chunk, filter_description.data); + + /// Filter the block by expression in HAVING. + for (auto & column : columns) + { + column = column->filter(*filter_description.data, -1); + if (column->empty()) + { + chunk.clear(); + return; + } + } + + auto num_rows = columns.front()->size(); + chunk.setColumns(std::move(columns), num_rows); + } + + passed_keys += chunk.getNumRows(); +} + +void TotalsHavingTransform::addToTotals(const Chunk & chunk, const IColumn::Filter * filter) +{ + auto num_columns = chunk.getNumColumns(); + for (size_t col = 0; col < num_columns; ++col) + { + const auto & current = chunk.getColumns()[col]; + + if (const auto * column = typeid_cast(current.get())) + { + auto & target = typeid_cast(*current_totals[col]); + IAggregateFunction * function = target.getAggregateFunction().get(); + AggregateDataPtr data = target.getData()[0]; + + /// Accumulate all aggregate states into that value. + + const ColumnAggregateFunction::Container & vec = column->getData(); + size_t size = vec.size(); + + if (filter) + { + for (size_t row = 0; row < size; ++row) + if ((*filter)[row]) + function->merge(data, vec[row], arena.get()); + } + else + { + for (size_t row = 0; row < size; ++row) + function->merge(data, vec[row], arena.get()); + } + } + } +} + +void TotalsHavingTransform::prepareTotals() +{ + /// If totals_mode == AFTER_HAVING_AUTO, you need to decide whether to add aggregates to TOTALS for strings, + /// not passed max_rows_to_group_by. + if (overflow_aggregates) + { + if (totals_mode == TotalsMode::BEFORE_HAVING + || totals_mode == TotalsMode::AFTER_HAVING_INCLUSIVE + || (totals_mode == TotalsMode::AFTER_HAVING_AUTO + && static_cast(passed_keys) / total_keys >= auto_include_threshold)) + addToTotals(overflow_aggregates, nullptr); + } + + totals = Chunk(std::move(current_totals), 1); + finalizeChunk(totals); + + if (expression) + { + auto block = finalized_header.cloneWithColumns(totals.detachColumns()); + expression->execute(block); + totals = Chunk(block.getColumns(), 1); + } +} + +} diff --git a/dbms/src/Processors/Transforms/TotalsHavingTransform.h b/dbms/src/Processors/Transforms/TotalsHavingTransform.h new file mode 100644 index 00000000000..71d1a899307 --- /dev/null +++ b/dbms/src/Processors/Transforms/TotalsHavingTransform.h @@ -0,0 +1,75 @@ +#include + +#include +#include + +namespace DB +{ + +class Arena; +using ArenaPtr = std::shared_ptr; + +class ExpressionActions; +using ExpressionActionsPtr = std::shared_ptr; + +/** Takes blocks after grouping, with non-finalized aggregate functions. + * Calculates total values according to totals_mode. + * If necessary, evaluates the expression from HAVING and filters rows. Returns the finalized and filtered blocks. + */ +class TotalsHavingTransform : public ISimpleTransform +{ +public: + TotalsHavingTransform( + const Block & header, + bool overflow_row_, + const ExpressionActionsPtr & expression_, + const std::string & filter_column_, + TotalsMode totals_mode_, + double auto_include_threshold_, + bool final_); + + String getName() const override { return "TotalsHavingTransform"; } + + OutputPort & getTotalsPort() { return outputs.back(); } + + Status prepare() override; + void work() override; + +protected: + void transform(Chunk & chunk) override; + + bool finished_transform = false; + Chunk totals; + +private: + void addToTotals(const Chunk & block, const IColumn::Filter * filter); + void prepareTotals(); + + /// Params + bool overflow_row; + ExpressionActionsPtr expression; + String filter_column_name; + TotalsMode totals_mode; + double auto_include_threshold; + bool final; + + size_t passed_keys = 0; + size_t total_keys = 0; + + size_t filter_column_pos = 0; + + Block finalized_header; + + /// Here are the values that did not pass max_rows_to_group_by. + /// They are added or not added to the current_totals, depending on the totals_mode. + Chunk overflow_aggregates; + + /// Here, total values are accumulated. After the work is finished, they will be placed in IBlockInputStream::totals. + MutableColumns current_totals; + /// Arena for aggregate function states in totals. + ArenaPtr arena; +}; + +void finalizeChunk(Chunk & chunk); + +} diff --git a/dbms/src/Processors/printPipeline.h b/dbms/src/Processors/printPipeline.h new file mode 100644 index 00000000000..d3e8e58b2ce --- /dev/null +++ b/dbms/src/Processors/printPipeline.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include + +namespace DB +{ + +/** Print pipeline in "dot" format for GraphViz. + * You can render it with: + * dot -T png < pipeline.dot > pipeline.png + */ + +template +void printPipeline(const Processors & processors, const Statuses & statuses, WriteBuffer & out) +{ + out << "digraph\n{\n"; + + auto get_proc_id = [](const IProcessor & proc) -> UInt64 + { + return reinterpret_cast(&proc); + }; + + auto statuses_iter = statuses.begin(); + + /// Nodes // TODO quoting and escaping + for (const auto & processor : processors) + { + out << "n" << get_proc_id(*processor) << "[label=\"" << processor->getName() << processor->getDescription(); + + if (statuses_iter != statuses.end()) + { + out << " (" << IProcessor::statusToName(*statuses_iter) << ")"; + ++statuses_iter; + } + + out << "\"];\n"; + } + + /// Edges + for (const auto & processor : processors) + { + for (const auto & port : processor->getOutputs()) + { + const IProcessor & curr = *processor; + const IProcessor & next = port.getInputPort().getProcessor(); + + out << "n" << get_proc_id(curr) << " -> " << "n" << get_proc_id(next) << ";\n"; + } + } + out << "}\n"; +} + +template +void printPipeline(const Processors & processors, WriteBuffer & out) +{ + printPipeline(processors, std::vector(), out); +} + +} diff --git a/dbms/src/Processors/tests/CMakeLists.txt b/dbms/src/Processors/tests/CMakeLists.txt new file mode 100644 index 00000000000..5f44ec2a8fd --- /dev/null +++ b/dbms/src/Processors/tests/CMakeLists.txt @@ -0,0 +1,15 @@ +add_executable (processors_test processors_test.cpp) +add_executable (processors_test_chain processors_test_chain.cpp) +add_executable (processors_test_merge processors_test_merge.cpp) +add_executable (processors_test_merging_sorted_transform processors_test_merging_sorted_transform.cpp) +add_executable (processors_test_merge_sorting_transform processors_test_merge_sorting_transform.cpp) +add_executable (processors_test_expand_pipeline processors_test_expand_pipeline.cpp) +add_executable (processors_test_aggregation processors_test_aggregation.cpp) + +target_link_libraries (processors_test dbms) +target_link_libraries (processors_test_chain dbms) +target_link_libraries (processors_test_merge dbms) +target_link_libraries (processors_test_expand_pipeline dbms) +target_link_libraries (processors_test_merging_sorted_transform dbms) +target_link_libraries (processors_test_merge_sorting_transform dbms) +target_link_libraries (processors_test_aggregation dbms clickhouse_aggregate_functions) diff --git a/dbms/src/Processors/tests/processors_test.cpp b/dbms/src/Processors/tests/processors_test.cpp new file mode 100644 index 00000000000..b663cf319ad --- /dev/null +++ b/dbms/src/Processors/tests/processors_test.cpp @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace DB; + + +class NumbersSource : public ISource +{ +public: + String getName() const override { return "Numbers"; } + + NumbersSource(UInt64 start_number, unsigned sleep_useconds) + : ISource(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + current_number(start_number), sleep_useconds(sleep_useconds) + { + } + +private: + UInt64 current_number = 0; + unsigned sleep_useconds; + + Chunk generate() override + { + usleep(sleep_useconds); + + MutableColumns columns; + columns.emplace_back(ColumnUInt64::create(1, current_number)); + ++current_number; + return Chunk(std::move(columns), 1); + } +}; + + +class SleepyNumbersSource : public IProcessor +{ +protected: + OutputPort & output; + +public: + String getName() const override { return "SleepyNumbers"; } + + SleepyNumbersSource(UInt64 start_number, unsigned sleep_useconds) + : IProcessor({}, {Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})}) + , output(outputs.front()), current_number(start_number), sleep_useconds(sleep_useconds) + { + } + + Status prepare() override + { + if (active) + return Status::Wait; + + if (output.isFinished()) + return Status::Finished; + + if (!output.canPush()) + return Status::PortFull; + + if (!current_chunk) + return Status::Async; + + output.push(std::move(current_chunk)); + return Status::Async; + } + + void schedule(EventCounter & watch) override + { + active = true; + pool.schedule([&watch, this] + { + usleep(sleep_useconds); + current_chunk = generate(); + active = false; + watch.notify(); + }); + } + + OutputPort & getPort() { return output; } + +private: + ThreadPool pool{1, 1, 0}; + Chunk current_chunk; + std::atomic_bool active {false}; + + UInt64 current_number = 0; + unsigned sleep_useconds; + + Chunk generate() + { + MutableColumns columns; + columns.emplace_back(ColumnUInt64::create(1, current_number)); + ++current_number; + return Chunk(std::move(columns), 1); + } +}; + + +class PrintSink : public ISink +{ +public: + String getName() const override { return "Print"; } + + PrintSink(String prefix) + : ISink(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + prefix(std::move(prefix)) + { + } + +private: + String prefix; + WriteBufferFromFileDescriptor out{STDOUT_FILENO}; + FormatSettings settings; + + void consume(Chunk chunk) override + { + size_t rows = chunk.getNumRows(); + size_t columns = chunk.getNumColumns(); + + for (size_t row_num = 0; row_num < rows; ++row_num) + { + writeString(prefix, out); + for (size_t column_num = 0; column_num < columns; ++column_num) + { + if (column_num != 0) + writeChar('\t', out); + getPort().getHeader().getByPosition(column_num).type->serializeAsText(*chunk.getColumns()[column_num], row_num, out, settings); + } + writeChar('\n', out); + } + + out.next(); + } +}; + + +int main(int, char **) +try +{ + auto source0 = std::make_shared(0, 300000); + auto header = source0->getPort().getHeader(); + auto limit0 = std::make_shared(header, 10, 0); + + connect(source0->getPort(), limit0->getInputPort()); + + auto queue = std::make_shared(header); + + connect(limit0->getOutputPort(), queue->getInputPort()); + + auto source1 = std::make_shared(100, 100000); + auto source2 = std::make_shared(1000, 200000); + + auto source3 = std::make_shared(10, 100000); + auto limit3 = std::make_shared(header, 5, 0); + + connect(source3->getPort(), limit3->getInputPort()); + + auto source4 = std::make_shared(10, 100000); + auto limit4 = std::make_shared(header, 5, 0); + + connect(source4->getPort(), limit4->getInputPort()); + + auto concat = std::make_shared(header, 2); + + connect(limit3->getOutputPort(), concat->getInputs().front()); + connect(limit4->getOutputPort(), concat->getInputs().back()); + + auto fork = std::make_shared(header, 2); + + connect(concat->getOutputPort(), fork->getInputPort()); + + auto print_after_concat = std::make_shared("---------- "); + + connect(fork->getOutputs().back(), print_after_concat->getPort()); + + auto resize = std::make_shared(header, 4, 1); + + auto input_it = resize->getInputs().begin(); + connect(queue->getOutputPort(), *(input_it++)); + connect(source1->getPort(), *(input_it++)); + connect(source2->getPort(), *(input_it++)); + connect(fork->getOutputs().front(), *(input_it++)); + + auto limit = std::make_shared(header, 100, 0); + + connect(resize->getOutputs().front(), limit->getInputPort()); + + auto sink = std::make_shared(""); + + connect(limit->getOutputPort(), sink->getPort()); + + WriteBufferFromOStream out(std::cout); + std::vector processors = {source0, source1, source2, source3, source4, limit0, limit3, limit4, limit, + queue, concat, fork, print_after_concat, resize, sink}; + printPipeline(processors, out); + + // ThreadPool pool(4, 4, 10); + PipelineExecutor executor(processors); + /// SequentialPipelineExecutor executor({sink}); + + executor.execute(1); + + return 0; +} +catch (...) +{ + std::cerr << getCurrentExceptionMessage(true) << '\n'; + throw; +} diff --git a/dbms/src/Processors/tests/processors_test_aggregation.cpp b/dbms/src/Processors/tests/processors_test_aggregation.cpp new file mode 100644 index 00000000000..116518391d6 --- /dev/null +++ b/dbms/src/Processors/tests/processors_test_aggregation.cpp @@ -0,0 +1,407 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace DB; + + +class NumbersSource : public ISource +{ +public: + String getName() const override { return "Numbers"; } + + NumbersSource(UInt64 start_number, UInt64 step, UInt64 block_size, unsigned sleep_useconds) + : ISource(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + current_number(start_number), step(step), block_size(block_size), sleep_useconds(sleep_useconds) + { + } + +private: + UInt64 current_number = 0; + UInt64 step; + UInt64 block_size; + unsigned sleep_useconds; + + Chunk generate() override + { + usleep(sleep_useconds); + + MutableColumns columns; + columns.emplace_back(ColumnUInt64::create()); + + for (UInt64 i = 0; i < block_size; ++i, current_number += step) + columns.back()->insert(Field(current_number)); + + return Chunk(std::move(columns), block_size); + } +}; + +class PrintSink : public ISink +{ +public: + String getName() const override { return "Print"; } + + PrintSink(String prefix, Block header) + : ISink(std::move(header)), + prefix(std::move(prefix)) + { + } + +private: + String prefix; + WriteBufferFromFileDescriptor out{STDOUT_FILENO}; + FormatSettings settings; + + void consume(Chunk chunk) override + { + size_t rows = chunk.getNumRows(); + size_t columns = chunk.getNumColumns(); + + for (size_t row_num = 0; row_num < rows; ++row_num) + { + writeString(prefix, out); + for (size_t column_num = 0; column_num < columns; ++column_num) + { + if (column_num != 0) + writeChar('\t', out); + getPort().getHeader().getByPosition(column_num).type->serializeAsText(*chunk.getColumns()[column_num], row_num, out, settings); + } + writeChar('\n', out); + } + + out.next(); + } +}; + +class CheckSink : public ISink +{ +public: + String getName() const override { return "Check"; } + + CheckSink(Block header, size_t num_rows) + : ISink(std::move(header)), read_rows(num_rows, false) + { + } + + void checkAllRead() + { + for (size_t i = 0; i < read_rows.size(); ++i) + { + if (!read_rows[i]) + { + throw Exception("Check Failed. Row " + toString(i) + " was not read.", ErrorCodes::LOGICAL_ERROR); + } + } + } + +private: + std::vector read_rows; + + void consume(Chunk chunk) override + { + size_t rows = chunk.getNumRows(); + size_t columns = chunk.getNumColumns(); + + for (size_t row_num = 0; row_num < rows; ++row_num) + { + std::vector values(columns); + for (size_t column_num = 0; column_num < columns; ++column_num) + { + values[column_num] = chunk.getColumns()[column_num]->getUInt(row_num); + } + + if (3 * values[0] != values[1]) + throw Exception("Check Failed. Got (" + toString(values[0]) + ", " + toString(values[1]) + ") in result," + + "but " + toString(values[0]) + " * 3 != " + toString(values[1]), + ErrorCodes::LOGICAL_ERROR); + + if (values[0] >= read_rows.size()) + throw Exception("Check Failed. Got string with number " + toString(values[0]) + + " (max " + toString(read_rows.size()), ErrorCodes::LOGICAL_ERROR); + + if (read_rows[values[0]]) + throw Exception("Row " + toString(values[0]) + " was already read.", ErrorCodes::LOGICAL_ERROR); + + read_rows[values[0]] = true; + } + } +}; + +template +struct measure +{ + template + static typename TimeT::rep execution(F&& func, Args&&... args) + { + auto start = std::chrono::steady_clock::now(); + std::forward(func)(std::forward(args)...); + auto duration = std::chrono::duration_cast< TimeT> + (std::chrono::steady_clock::now() - start); + return duration.count(); + } +}; + +int main(int, char **) +try +{ + ThreadStatus thread_status; + CurrentThread::initializeQuery(); + auto thread_group = CurrentThread::getGroup(); + + Poco::AutoPtr channel = new Poco::ConsoleChannel(std::cerr); + Logger::root().setChannel(channel); + Logger::root().setLevel("trace"); + + registerAggregateFunctions(); + auto & factory = AggregateFunctionFactory::instance(); + + auto cur_path = Poco::Path().absolute().toString(); + + auto execute_one_stream = [&](String msg, size_t num_threads, bool two_level, bool external) + { + std::cerr << '\n' << msg << "\n"; + + size_t num_rows = 1000000; + size_t block_size = 1000; + + auto source1 = std::make_shared(0, 1, block_size, 0); + auto source2 = std::make_shared(0, 1, block_size, 0); + auto source3 = std::make_shared(0, 1, block_size, 0); + + auto limit1 = std::make_shared(source1->getPort().getHeader(), num_rows, 0); + auto limit2 = std::make_shared(source2->getPort().getHeader(), num_rows, 0); + auto limit3 = std::make_shared(source3->getPort().getHeader(), num_rows, 0); + + auto resize = std::make_shared(source1->getPort().getHeader(), 3, 1); + + AggregateDescriptions aggregate_descriptions(1); + + DataTypes sum_types = { std::make_shared() }; + aggregate_descriptions[0].function = factory.get("sum", sum_types); + aggregate_descriptions[0].arguments = {0}; + + bool overflow_row = false; /// Without overflow row. + size_t max_rows_to_group_by = 0; /// All. + size_t group_by_two_level_threshold = two_level ? 10 : 0; + size_t group_by_two_level_threshold_bytes = two_level ? 128 : 0; + size_t max_bytes_before_external_group_by = external ? 10000000 : 0; + + Aggregator::Params params( + source1->getPort().getHeader(), + {0}, + aggregate_descriptions, + overflow_row, + max_rows_to_group_by, + OverflowMode::THROW, + nullptr, /// No compiler + 0, /// min_count_to_compile + group_by_two_level_threshold, + group_by_two_level_threshold_bytes, + max_bytes_before_external_group_by, + false, /// empty_result_for_aggregation_by_empty_set + cur_path, /// tmp_path + 1 /// max_threads + ); + + auto agg_params = std::make_shared(params, /* final =*/ false); + auto merge_params = std::make_shared(params, /* final =*/ true); + auto aggregating = std::make_shared(source1->getPort().getHeader(), agg_params); + auto merging = std::make_shared(aggregating->getOutputs().front().getHeader(), merge_params, 4); + auto sink = std::make_shared(merging->getOutputPort().getHeader(), num_rows); + + connect(source1->getPort(), limit1->getInputPort()); + connect(source2->getPort(), limit2->getInputPort()); + connect(source3->getPort(), limit3->getInputPort()); + + auto it = resize->getInputs().begin(); + connect(limit1->getOutputPort(), *(it++)); + connect(limit2->getOutputPort(), *(it++)); + connect(limit3->getOutputPort(), *(it++)); + + connect(resize->getOutputs().front(), aggregating->getInputs().front()); + connect(aggregating->getOutputs().front(), merging->getInputPort()); + connect(merging->getOutputPort(), sink->getPort()); + + std::vector processors = {source1, source2, source3, + limit1, limit2, limit3, + resize, aggregating, merging, sink}; +// WriteBufferFromOStream out(std::cout); +// printPipeline(processors, out); + + PipelineExecutor executor(processors); + executor.execute(num_threads); + sink->checkAllRead(); + }; + + auto execute_mult_streams = [&](String msg, size_t num_threads, bool two_level, bool external) + { + std::cerr << '\n' << msg << "\n"; + + size_t num_rows = 1000000; + size_t block_size = 1000; + + auto source1 = std::make_shared(0, 1, block_size, 0); + auto source2 = std::make_shared(0, 1, block_size, 0); + auto source3 = std::make_shared(0, 1, block_size, 0); + + auto limit1 = std::make_shared(source1->getPort().getHeader(), num_rows, 0); + auto limit2 = std::make_shared(source2->getPort().getHeader(), num_rows, 0); + auto limit3 = std::make_shared(source3->getPort().getHeader(), num_rows, 0); + + AggregateDescriptions aggregate_descriptions(1); + + DataTypes sum_types = { std::make_shared() }; + aggregate_descriptions[0].function = factory.get("sum", sum_types); + aggregate_descriptions[0].arguments = {0}; + + bool overflow_row = false; /// Without overflow row. + size_t max_rows_to_group_by = 0; /// All. + size_t group_by_two_level_threshold = two_level ? 10 : 0; + size_t group_by_two_level_threshold_bytes = two_level ? 128 : 0; + size_t max_bytes_before_external_group_by = external ? 10000000 : 0; + + Aggregator::Params params( + source1->getPort().getHeader(), + {0}, + aggregate_descriptions, + overflow_row, + max_rows_to_group_by, + OverflowMode::THROW, + nullptr, /// No compiler + 0, /// min_count_to_compile + group_by_two_level_threshold, + group_by_two_level_threshold_bytes, + max_bytes_before_external_group_by, + false, /// empty_result_for_aggregation_by_empty_set + cur_path, /// tmp_path + 1 /// max_threads + ); + + auto agg_params = std::make_shared(params, /* final =*/ false); + auto merge_params = std::make_shared(params, /* final =*/ true); + + ManyAggregatedDataPtr data = std::make_unique(3); + + auto aggregating1 = std::make_shared(source1->getPort().getHeader(), agg_params, data, 0, 4, 4); + auto aggregating2 = std::make_shared(source1->getPort().getHeader(), agg_params, data, 1, 4, 4); + auto aggregating3 = std::make_shared(source1->getPort().getHeader(), agg_params, data, 2, 4, 4); + + Processors merging_pipe = createMergingAggregatedMemoryEfficientPipe( + aggregating1->getOutputs().front().getHeader(), + merge_params, + 3, 2); + + auto sink = std::make_shared(merging_pipe.back()->getOutputs().back().getHeader(), num_rows); + + connect(source1->getPort(), limit1->getInputPort()); + connect(source2->getPort(), limit2->getInputPort()); + connect(source3->getPort(), limit3->getInputPort()); + + connect(limit1->getOutputPort(), aggregating1->getInputs().front()); + connect(limit2->getOutputPort(), aggregating2->getInputs().front()); + connect(limit3->getOutputPort(), aggregating3->getInputs().front()); + + auto it = merging_pipe.front()->getInputs().begin(); + connect(aggregating1->getOutputs().front(), *(it++)); + connect(aggregating2->getOutputs().front(), *(it++)); + connect(aggregating3->getOutputs().front(), *(it++)); + + connect(merging_pipe.back()->getOutputs().back(), sink->getPort()); + + std::vector processors = {source1, source2, source3, + limit1, limit2, limit3, + aggregating1, aggregating2, aggregating3, sink}; + + processors.insert(processors.end(), merging_pipe.begin(), merging_pipe.end()); +// WriteBufferFromOStream out(std::cout); +// printPipeline(processors, out); + + PipelineExecutor executor(processors); + executor.execute(num_threads); + sink->checkAllRead(); + }; + + std::vector messages; + std::vector times; + + auto exec = [&](auto func, String msg, size_t num_threads, bool two_level, bool external) + { + msg += ", two_level = " + toString(two_level) + ", external = " + toString(external); + Int64 time = 0; + + auto wrapper = [&]() + { + ThreadStatus cur_status; + + CurrentThread::attachToIfDetached(thread_group); + time = measure<>::execution(func, msg, num_threads, two_level, external); + }; + + std::thread thread(wrapper); + thread.join(); + + messages.emplace_back(msg); + times.emplace_back(time); + }; + + size_t num_threads = 4; + + exec(execute_one_stream, "One stream, single thread", 1, false, false); + exec(execute_one_stream, "One stream, multiple threads", num_threads, false, false); + + exec(execute_mult_streams, "Multiple streams, single thread", 1, false, false); + exec(execute_mult_streams, "Multiple streams, multiple threads", num_threads, false, false); + + exec(execute_one_stream, "One stream, single thread", 1, true, false); + exec(execute_one_stream, "One stream, multiple threads", num_threads, true, false); + + exec(execute_mult_streams, "Multiple streams, single thread", 1, true, false); + exec(execute_mult_streams, "Multiple streams, multiple threads", num_threads, true, false); + + exec(execute_one_stream, "One stream, single thread", 1, true, true); + exec(execute_one_stream, "One stream, multiple threads", num_threads, true, true); + + exec(execute_mult_streams, "Multiple streams, single thread", 1, true, true); + exec(execute_mult_streams, "Multiple streams, multiple threads", num_threads, true, true); + + for (size_t i = 0; i < messages.size(); ++i) + std::cout << messages[i] << " time: " << times[i] << " ms.\n"; + + return 0; +} +catch (...) +{ + std::cerr << getCurrentExceptionMessage(true) << '\n'; + throw; +} diff --git a/dbms/src/Processors/tests/processors_test_chain.cpp b/dbms/src/Processors/tests/processors_test_chain.cpp new file mode 100644 index 00000000000..dfcd2c6b5ee --- /dev/null +++ b/dbms/src/Processors/tests/processors_test_chain.cpp @@ -0,0 +1,165 @@ +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + + +using namespace DB; + + +class NumbersSource : public ISource +{ +public: + String getName() const override { return "Numbers"; } + + NumbersSource(UInt64 start_number, unsigned sleep_useconds) + : ISource(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + current_number(start_number), sleep_useconds(sleep_useconds) + { + } + +private: + UInt64 current_number = 0; + unsigned sleep_useconds; + + Chunk generate() override + { + usleep(sleep_useconds); + + MutableColumns columns; + columns.emplace_back(ColumnUInt64::create(1, current_number)); + ++current_number; + return Chunk(std::move(columns), 1); + } +}; + +class SleepyTransform : public ISimpleTransform +{ +public: + explicit SleepyTransform(unsigned sleep_useconds) + : ISimpleTransform( + Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }}), + Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }}), + /*skip_empty_chunks =*/ false) + , sleep_useconds(sleep_useconds) {} + + String getName() const override { return "SleepyTransform"; } + +protected: + void transform(Chunk &) override + { + usleep(sleep_useconds); + } + +private: + unsigned sleep_useconds; +}; + +class PrintSink : public ISink +{ +public: + String getName() const override { return "Print"; } + + PrintSink(String prefix) + : ISink(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + prefix(std::move(prefix)) + { + } + +private: + String prefix; + WriteBufferFromFileDescriptor out{STDOUT_FILENO}; + FormatSettings settings; + + void consume(Chunk chunk) override + { + size_t rows = chunk.getNumRows(); + size_t columns = chunk.getNumColumns(); + + for (size_t row_num = 0; row_num < rows; ++row_num) + { + writeString(prefix, out); + for (size_t column_num = 0; column_num < columns; ++column_num) + { + if (column_num != 0) + writeChar('\t', out); + getPort().getHeader().getByPosition(column_num).type->serializeAsText(*chunk.getColumns()[column_num], row_num, out, settings); + } + writeChar('\n', out); + } + + out.next(); + } +}; + +template +struct measure +{ + template + static typename TimeT::rep execution(F&& func, Args&&... args) + { + auto start = std::chrono::steady_clock::now(); + std::forward(func)(std::forward(args)...); + auto duration = std::chrono::duration_cast< TimeT> + (std::chrono::steady_clock::now() - start); + return duration.count(); + } +}; + +int main(int, char **) +try +{ + auto execute_chain = [](size_t num_threads) + { + std::cerr << "---------------------\n"; + + auto source = std::make_shared(0, 100000); + auto transform1 = std::make_shared(100000); + auto transform2 = std::make_shared(100000); + auto transform3 = std::make_shared(100000); + auto limit = std::make_shared(source->getPort().getHeader(), 20, 0); + auto sink = std::make_shared(""); + + connect(source->getPort(), transform1->getInputPort()); + connect(transform1->getOutputPort(), transform2->getInputPort()); + connect(transform2->getOutputPort(), transform3->getInputPort()); + connect(transform3->getOutputPort(), limit->getInputPort()); + connect(limit->getOutputPort(), sink->getPort()); + + std::vector processors = {source, transform1, transform2, transform3, limit, sink}; +// WriteBufferFromOStream out(std::cout); +// printPipeline(processors, out); + + PipelineExecutor executor(processors); + executor.execute(num_threads); + }; + + auto time_single = measure<>::execution(execute_chain, 1); + auto time_mt = measure<>::execution(execute_chain, 4); + + std::cout << "Single Thread time: " << time_single << " ms.\n"; + std::cout << "Multiple Threads time: " << time_mt << " ms.\n"; + + return 0; +} +catch (...) +{ + std::cerr << getCurrentExceptionMessage(true) << '\n'; + throw; +} diff --git a/dbms/src/Processors/tests/processors_test_expand_pipeline.cpp b/dbms/src/Processors/tests/processors_test_expand_pipeline.cpp new file mode 100644 index 00000000000..fa977dc7ba8 --- /dev/null +++ b/dbms/src/Processors/tests/processors_test_expand_pipeline.cpp @@ -0,0 +1,285 @@ +#include + +#include + +#include +#include +#include +#include +#include + + +#include +#include +#include + +#include + +#include +#include +#include + +using namespace DB; + +class PrintSink : public ISink +{ +public: + String getName() const override { return "Print"; } + + PrintSink(String prefix) + : ISink(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + prefix(std::move(prefix)) + { + } + +private: + String prefix; + WriteBufferFromFileDescriptor out{STDOUT_FILENO}; + FormatSettings settings; + + void consume(Chunk chunk) override + { + size_t rows = chunk.getNumRows(); + size_t columns = chunk.getNumColumns(); + + for (size_t row_num = 0; row_num < rows; ++row_num) + { + writeString(prefix, out); + for (size_t column_num = 0; column_num < columns; ++column_num) + { + if (column_num != 0) + writeChar('\t', out); + getPort().getHeader().getByPosition(column_num).type->serializeAsText(*chunk.getColumns()[column_num], row_num, out, settings); + } + writeChar('\n', out); + } + + out.next(); + } +}; + + +class OneNumberSource : public ISource +{ +public: + String getName() const override { return "OneNumber"; } + + OneNumberSource(UInt64 number) + : ISource(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + number(number) + { + } + +private: + UInt64 number; + bool done = false; + + Chunk generate() override + { + if (done) + return Chunk(); + + done = true; + + MutableColumns columns; + columns.emplace_back(ColumnUInt64::create(1, number)); + return Chunk(std::move(columns), 1); + } +}; + + +class ExpandingProcessor : public IProcessor +{ +public: + String getName() const override { return "Expanding"; } + ExpandingProcessor() + : IProcessor({Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})}, + {Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})}) + {} + + Status prepare() override + { + auto & main_input = inputs.front(); + auto & main_output = outputs.front(); + auto & additional_input = inputs.back(); + auto & additional_output = outputs.back(); + /// Check can output. + + + if (main_output.isFinished()) + { + main_input.close(); + additional_input.close(); + additional_output.finish(); + return Status::Finished; + } + + if (!main_output.canPush()) + { + main_input.setNotNeeded(); + additional_input.setNotNeeded(); + return Status::PortFull; + } + + if (chunk_from_add_inp && is_processed) + { + if (is_processed) + main_output.push(std::move(chunk_from_add_inp)); + else + return Status::Ready; + } + + if (expanded) + { + if (chunk_from_main_inp) + { + if (additional_output.isFinished()) + { + main_input.close(); + return Status::Finished; + } + + if (!additional_output.canPush()) + { + main_input.setNotNeeded(); + return Status::PortFull; + } + + additional_output.push(std::move(chunk_from_main_inp)); + main_input.close(); + } + + if (additional_input.isFinished()) + { + main_output.finish(); + return Status::Finished; + } + + additional_input.setNeeded(); + + if (!additional_input.hasData()) + return Status::NeedData; + + chunk_from_add_inp = additional_input.pull(); + is_processed = false; + return Status::Ready; + } + else + { + if (!chunk_from_main_inp) + { + + if (main_input.isFinished()) + { + main_output.finish(); + return Status::Finished; + } + + main_input.setNeeded(); + + if (!main_input.hasData()) + return Status::NeedData; + + chunk_from_main_inp = main_input.pull(); + main_input.close(); + } + + UInt64 val = chunk_from_main_inp.getColumns()[0]->getUInt(0); + if (val) + { + --val; + chunk_from_main_inp.setColumns(Columns{ColumnUInt64::create(1, val)}, 1); + return Status::ExpandPipeline; + } + + main_output.push(std::move(chunk_from_main_inp)); + main_output.finish(); + return Status::Finished; + } + } + + Processors expandPipeline() override + { + auto & main_input = inputs.front(); + auto & main_output = outputs.front(); + + Processors processors = {std::make_shared()}; + inputs.push_back({main_input.getHeader(), this}); + outputs.push_back({main_output.getHeader(), this}); + connect(outputs.back(), processors.back()->getInputs().front()); + connect(processors.back()->getOutputs().front(), inputs.back()); + inputs.back().setNeeded(); + + expanded = true; + return processors; + } + + void work() override + { + auto num_rows = chunk_from_add_inp.getNumRows(); + auto columns = chunk_from_add_inp.mutateColumns(); + columns.front()->insert(Field(num_rows)); + chunk_from_add_inp.setColumns(std::move(columns), num_rows + 1); + is_processed = true; + } + +private: + bool expanded = false; + Chunk chunk_from_main_inp; + Chunk chunk_from_add_inp; + bool is_processed = false; +}; + + +template +struct measure +{ + template + static typename TimeT::rep execution(F&& func, Args&&... args) + { + auto start = std::chrono::steady_clock::now(); + std::forward(func)(std::forward(args)...); + auto duration = std::chrono::duration_cast< TimeT> + (std::chrono::steady_clock::now() - start); + return duration.count(); + } +}; + +int main(int, char **) +try +{ + auto execute = [](String msg, size_t num, size_t num_threads) + { + std::cerr << msg << "\n"; + + auto source = std::make_shared(num); + auto expanding = std::make_shared(); + auto sink = std::make_shared(""); + + connect(source->getPort(), expanding->getInputs().front()); + connect(expanding->getOutputs().front(), sink->getPort()); + + std::vector processors = {source, expanding, sink}; + + PipelineExecutor executor(processors); + executor.execute(num_threads); + + WriteBufferFromOStream out(std::cout); + printPipeline(executor.getProcessors(), out); + }; + + ThreadPool pool(4, 4, 10); + + auto time_single = measure<>::execution(execute, "Single thread", 10, 1); + auto time_mt = measure<>::execution(execute, "Multiple threads", 10, 4); + + std::cout << "Single Thread time: " << time_single << " ms.\n"; + std::cout << "Multiple Threads time:" << time_mt << " ms.\n"; + + return 0; +} +catch (...) +{ + std::cerr << getCurrentExceptionMessage(true) << '\n'; + throw; +} diff --git a/dbms/src/Processors/tests/processors_test_merge.cpp b/dbms/src/Processors/tests/processors_test_merge.cpp new file mode 100644 index 00000000000..00e322430e5 --- /dev/null +++ b/dbms/src/Processors/tests/processors_test_merge.cpp @@ -0,0 +1,334 @@ +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + + +using namespace DB; + + +class MergingSortedProcessor : public IProcessor +{ +public: + MergingSortedProcessor(const Block & header, size_t num_inputs) + : IProcessor(InputPorts(num_inputs, header), OutputPorts{header}) + , chunks(num_inputs), positions(num_inputs, 0), finished(num_inputs, false) + { + } + + String getName() const override { return "MergingSortedProcessor"; } + + Status prepare() override + { + auto & output = outputs.front(); + + /// Check can output. + + if (output.isFinished()) + { + for (auto & in : inputs) + in.close(); + + return Status::Finished; + } + + if (!output.isNeeded()) + { + for (auto & in : inputs) + in.setNotNeeded(); + + return Status::PortFull; + } + + if (output.hasData()) + return Status::PortFull; + + /// Push if has data. + if (res) + { + output.push(std::move(res)); + return Status::PortFull; + } + + /// Check for inputs we need. + bool all_inputs_finished = true; + bool all_inputs_has_data = true; + auto it = inputs.begin(); + for (size_t i = 0; it != inputs.end(); ++it, ++i) + { + auto & input = *it; + if (!finished[i]) + { + if (!input.isFinished()) + { + all_inputs_finished = false; + bool needed = positions[i] >= chunks[i].getNumRows(); + if (needed) + { + input.setNeeded(); + if (input.hasData()) + { + chunks[i] = input.pull(); + positions[i] = 0; + } + else + all_inputs_has_data = false; + } + else + input.setNotNeeded(); + } + else + finished[i] = true; + } + } + + if (all_inputs_finished) + { + output.finish(); + return Status::Finished; + } + + if (!all_inputs_has_data) + return Status::NeedData; + + return Status::Ready; + } + + void work() override + { + using Key = std::pair; + std::priority_queue, std::greater<>> queue; + for (size_t i = 0; i < chunks.size(); ++i) + { + if (finished[i]) + continue; + + if (positions[i] >= chunks[i].getNumRows()) + return; + + queue.push({chunks[i].getColumns()[0]->getUInt(positions[i]), i}); + } + + auto col = ColumnUInt64::create(); + + while (!queue.empty()) + { + size_t ps = queue.top().second; + queue.pop(); + + auto & cur_col = chunks[ps].getColumns()[0]; + col->insertFrom(*cur_col, positions[ps]); + ++positions[ps]; + + if (positions[ps] == cur_col->size()) + break; + + queue.push({cur_col->getUInt(positions[ps]), ps}); + } + + UInt64 num_rows = col->size(); + res.setColumns(Columns({std::move(col)}), num_rows); + } + + OutputPort & getOutputPort() { return outputs.front(); } + +private: + Chunks chunks; + Chunk res; + std::vector positions; + std::vector finished; +}; + + +class NumbersSource : public ISource +{ +public: + String getName() const override { return "Numbers"; } + + NumbersSource(UInt64 start_number, UInt64 step, unsigned sleep_useconds) + : ISource(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + current_number(start_number), step(step), sleep_useconds(sleep_useconds) + { + } + +private: + UInt64 current_number = 0; + UInt64 step; + unsigned sleep_useconds; + + Chunk generate() override + { + usleep(sleep_useconds); + + MutableColumns columns; + columns.emplace_back(ColumnUInt64::create(1, current_number)); + current_number += step; + return Chunk(std::move(columns), 1); + } +}; + + +class SleepyTransform : public ISimpleTransform +{ +public: + explicit SleepyTransform(unsigned sleep_useconds) + : ISimpleTransform( + Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }}), + Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }}), + false) + , sleep_useconds(sleep_useconds) {} + + String getName() const override { return "SleepyTransform"; } + +protected: + void transform(Chunk &) override + { + usleep(sleep_useconds); + } + +private: + unsigned sleep_useconds; +}; + +class PrintSink : public ISink +{ +public: + String getName() const override { return "Print"; } + + PrintSink(String prefix) + : ISink(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + prefix(std::move(prefix)) + { + } + +private: + String prefix; + WriteBufferFromFileDescriptor out{STDOUT_FILENO}; + FormatSettings settings; + + void consume(Chunk chunk) override + { + size_t rows = chunk.getNumRows(); + size_t columns = chunk.getNumColumns(); + + for (size_t row_num = 0; row_num < rows; ++row_num) + { + writeString(prefix, out); + for (size_t column_num = 0; column_num < columns; ++column_num) + { + if (column_num != 0) + writeChar('\t', out); + getPort().getHeader().getByPosition(column_num).type->serializeAsText(*chunk.getColumns()[column_num], row_num, out, settings); + } + writeChar('\n', out); + } + + out.next(); + } +}; + +template +struct measure +{ + template + static typename TimeT::rep execution(F&& func, Args&&... args) + { + auto start = std::chrono::steady_clock::now(); + std::forward(func)(std::forward(args)...); + auto duration = std::chrono::duration_cast< TimeT> + (std::chrono::steady_clock::now() - start); + return duration.count(); + } +}; + +int main(int, char **) +try +{ + auto execute_chain = [](String msg, size_t start1, size_t start2, size_t start3, size_t num_threads) + { + std::cerr << msg << "\n"; + + auto source1 = std::make_shared(start1, 3, 100000); + auto source2 = std::make_shared(start2, 3, 100000); + auto source3 = std::make_shared(start3, 3, 100000); + + auto transform1 = std::make_shared(100000); + auto transform2 = std::make_shared(100000); + auto transform3 = std::make_shared(100000); + + auto limit1 = std::make_shared(source1->getPort().getHeader(), 20, 0); + auto limit2 = std::make_shared(source2->getPort().getHeader(), 20, 0); + auto limit3 = std::make_shared(source3->getPort().getHeader(), 20, 0); + + auto merge = std::make_shared(source1->getPort().getHeader(), 3); + auto limit_fin = std::make_shared(source1->getPort().getHeader(), 54, 0); + auto sink = std::make_shared(""); + + connect(source1->getPort(), transform1->getInputPort()); + connect(source2->getPort(), transform2->getInputPort()); + connect(source3->getPort(), transform3->getInputPort()); + + connect(transform1->getOutputPort(), limit1->getInputPort()); + connect(transform2->getOutputPort(), limit2->getInputPort()); + connect(transform3->getOutputPort(), limit3->getInputPort()); + + auto it = merge->getInputs().begin(); + connect(limit1->getOutputPort(), *(it++)); + connect(limit2->getOutputPort(), *(it++)); + connect(limit3->getOutputPort(), *(it++)); + + connect(merge->getOutputPort(), limit_fin->getInputPort()); + connect(limit_fin->getOutputPort(), sink->getPort()); + + std::vector processors = {source1, source2, source3, + transform1, transform2, transform3, + limit1, limit2, limit3, + merge, limit_fin, sink}; +// WriteBufferFromOStream out(std::cout); +// printPipeline(processors, out); + + PipelineExecutor executor(processors); + executor.execute(num_threads); + }; + + auto even_time_single = measure<>::execution(execute_chain, "Even distribution single thread", 0, 1, 2, 1); + auto even_time_mt = measure<>::execution(execute_chain, "Even distribution multiple threads", 0, 1, 2, 4); + + auto half_time_single = measure<>::execution(execute_chain, "Half distribution single thread", 0, 31, 62, 1); + auto half_time_mt = measure<>::execution(execute_chain, "Half distribution multiple threads", 0, 31, 62, 4); + + auto ordered_time_single = measure<>::execution(execute_chain, "Ordered distribution single thread", 0, 61, 122, 1); + auto ordered_time_mt = measure<>::execution(execute_chain, "Ordered distribution multiple threads", 0, 61, 122, 4); + + std::cout << "Single Thread [0:60:3] [1:60:3] [2:60:3] time: " << even_time_single << " ms.\n"; + std::cout << "Multiple Threads [0:60:3] [1:60:3] [2:60:3] time:" << even_time_mt << " ms.\n"; + + std::cout << "Single Thread [0:60:3] [31:90:3] [62:120:3] time: " << half_time_single << " ms.\n"; + std::cout << "Multiple Threads [0:60:3] [31:90:3] [62:120:3] time: " << half_time_mt << " ms.\n"; + + std::cout << "Single Thread [0:60:3] [61:120:3] [122:180:3] time: " << ordered_time_single << " ms.\n"; + std::cout << "Multiple Threads [0:60:3] [61:120:3] [122:180:3] time: " << ordered_time_mt << " ms.\n"; + + return 0; +} +catch (...) +{ + std::cerr << getCurrentExceptionMessage(true) << '\n'; + throw; +} diff --git a/dbms/src/Processors/tests/processors_test_merge_sorting_transform.cpp b/dbms/src/Processors/tests/processors_test_merge_sorting_transform.cpp new file mode 100644 index 00000000000..258e89e67e7 --- /dev/null +++ b/dbms/src/Processors/tests/processors_test_merge_sorting_transform.cpp @@ -0,0 +1,233 @@ +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + + +using namespace DB; + + +class NumbersSource : public ISource +{ +public: + String getName() const override { return "Numbers"; } + + NumbersSource(UInt64 count, UInt64 block_size, unsigned sleep_useconds) + : ISource(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + count(count), block_size(block_size), sleep_useconds(sleep_useconds) + { + } + +private: + UInt64 current_number = 0; + UInt64 count; + UInt64 block_size; + unsigned sleep_useconds; + + Chunk generate() override + { + if (current_number == count) + return {}; + + usleep(sleep_useconds); + + MutableColumns columns; + columns.emplace_back(ColumnUInt64::create()); + + UInt64 number = current_number++; + for (UInt64 i = 0; i < block_size; ++i, number += count) + columns.back()->insert(Field(number)); + + return Chunk(std::move(columns), block_size); + } +}; + +class CheckSortedSink : public ISink +{ +public: + String getName() const override { return "Print"; } + + CheckSortedSink() + : ISink(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})) + { + } + +private: + FormatSettings settings; + UInt64 current_number = 0; + + void consume(Chunk chunk) override + { + size_t rows = chunk.getNumRows(); + + UInt64 prev = current_number; + auto & col = chunk.getColumns().at(0); + for (size_t row_num = 0; row_num < rows; ++row_num) + { + UInt64 val = col->getUInt(row_num); + if (val != current_number) + throw Exception("Invalid value. Expected " + toString(current_number) + ", got " + toString(val), + ErrorCodes::LOGICAL_ERROR); + + ++current_number; + } + + std::cout << "CheckSortedSink: " << prev << " - " << current_number << std::endl; + } +}; + +template +struct measure +{ + template + static typename TimeT::rep execution(F&& func, Args&&... args) + { + auto start = std::chrono::steady_clock::now(); + std::forward(func)(std::forward(args)...); + auto duration = std::chrono::duration_cast< TimeT> + (std::chrono::steady_clock::now() - start); + return duration.count(); + } +}; + +int main(int, char **) +try +{ + Poco::AutoPtr channel = new Poco::ConsoleChannel(std::cerr); + Logger::root().setChannel(channel); + Logger::root().setLevel("trace"); + + auto execute_chain = []( + String msg, + UInt64 source_block_size, + UInt64 blocks_count, + size_t max_merged_block_size, + UInt64 limit, + size_t max_bytes_before_remerge, + size_t max_bytes_before_external_sort, + size_t num_threads) + { + std::cerr << "------------------------\n"; + std::cerr << msg << "\n"; + + auto source = std::make_shared(blocks_count, source_block_size, 100); + SortDescription description = {{0, 1, 1}}; + auto transform = std::make_shared( + source->getPort().getHeader(), description, + max_merged_block_size, limit, max_bytes_before_remerge, max_bytes_before_external_sort, "."); + auto sink = std::make_shared(); + + connect(source->getPort(), transform->getInputs().front()); + connect(transform->getOutputs().front(), sink->getPort()); + + std::vector processors = {source, transform, sink}; + PipelineExecutor executor(processors); + executor.execute(num_threads); + + WriteBufferFromOStream out(std::cout); + printPipeline(executor.getProcessors(), out); + }; + + std::map times; + + for (size_t num_threads : {1, 4}) + { + { + UInt64 source_block_size = 100; + UInt64 blocks_count = 10; + size_t max_merged_block_size = 100; + UInt64 limit = 0; + size_t max_bytes_before_remerge = 10000000; + size_t max_bytes_before_external_sort = 10000000; + std::string msg = num_threads > 1 ? "multiple threads" : "single thread"; + msg += ", " + toString(blocks_count) + " blocks per " + toString(source_block_size) + " numbers" + + ", no remerge and external sorts."; + + Int64 time = measure<>::execution(execute_chain, msg, + source_block_size, + blocks_count, + max_merged_block_size, + limit, + max_bytes_before_remerge, + max_bytes_before_external_sort, + num_threads); + + times[msg] = time; + } + + { + UInt64 source_block_size = 1024; + UInt64 blocks_count = 10; + size_t max_merged_block_size = 1024; + UInt64 limit = 2048; + size_t max_bytes_before_remerge = sizeof(UInt64) * source_block_size * 4; + size_t max_bytes_before_external_sort = 10000000; + std::string msg = num_threads > 1 ? "multiple threads" : "single thread"; + msg += ", " + toString(blocks_count) + " blocks per " + toString(source_block_size) + " numbers" + + ", with remerge, no external sorts."; + + Int64 time = measure<>::execution(execute_chain, msg, + source_block_size, + blocks_count, + max_merged_block_size, + limit, + max_bytes_before_remerge, + max_bytes_before_external_sort, + num_threads); + + times[msg] = time; + } + + { + UInt64 source_block_size = 1024; + UInt64 blocks_count = 10; + size_t max_merged_block_size = 1024; + UInt64 limit = 0; + size_t max_bytes_before_remerge = 0; + size_t max_bytes_before_external_sort = sizeof(UInt64) * source_block_size * 4; + std::string msg = num_threads > 1 ? "multiple threads" : "single thread"; + msg += ", " + toString(blocks_count) + " blocks per " + toString(source_block_size) + " numbers" + + ", no remerge, with external sorts."; + + Int64 time = measure<>::execution(execute_chain, msg, + source_block_size, + blocks_count, + max_merged_block_size, + limit, + max_bytes_before_remerge, + max_bytes_before_external_sort, + num_threads); + + times[msg] = time; + } + } + + for (auto & item : times) + std::cout << item.first << ' ' << item.second << " ms.\n"; + + return 0; +} +catch (...) +{ + std::cerr << getCurrentExceptionMessage(true) << '\n'; + throw; +} diff --git a/dbms/src/Processors/tests/processors_test_merging_sorted_transform.cpp b/dbms/src/Processors/tests/processors_test_merging_sorted_transform.cpp new file mode 100644 index 00000000000..214044dfd31 --- /dev/null +++ b/dbms/src/Processors/tests/processors_test_merging_sorted_transform.cpp @@ -0,0 +1,207 @@ +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + + +using namespace DB; + + +class NumbersSource : public ISource +{ +public: + String getName() const override { return "Numbers"; } + + NumbersSource(UInt64 start_number, UInt64 step, UInt64 block_size, unsigned sleep_useconds) + : ISource(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + current_number(start_number), step(step), block_size(block_size), sleep_useconds(sleep_useconds) + { + } + +private: + UInt64 current_number = 0; + UInt64 step; + UInt64 block_size; + unsigned sleep_useconds; + + Chunk generate() override + { + usleep(sleep_useconds); + + MutableColumns columns; + columns.emplace_back(ColumnUInt64::create()); + + for (UInt64 i = 0; i < block_size; ++i, current_number += step) + columns.back()->insert(Field(current_number)); + + return Chunk(std::move(columns), block_size); + } +}; + + +class SleepyTransform : public ISimpleTransform +{ +public: + explicit SleepyTransform(unsigned sleep_useconds) + : ISimpleTransform( + Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }}), + Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }}), + false) + , sleep_useconds(sleep_useconds) {} + + String getName() const override { return "SleepyTransform"; } + +protected: + void transform(Chunk &) override + { + usleep(sleep_useconds); + } + +private: + unsigned sleep_useconds; +}; + +class PrintSink : public ISink +{ +public: + String getName() const override { return "Print"; } + + PrintSink(String prefix) + : ISink(Block({ColumnWithTypeAndName{ ColumnUInt64::create(), std::make_shared(), "number" }})), + prefix(std::move(prefix)) + { + } + +private: + String prefix; + WriteBufferFromFileDescriptor out{STDOUT_FILENO}; + FormatSettings settings; + + void consume(Chunk chunk) override + { + size_t rows = chunk.getNumRows(); + size_t columns = chunk.getNumColumns(); + + for (size_t row_num = 0; row_num < rows; ++row_num) + { + writeString(prefix, out); + for (size_t column_num = 0; column_num < columns; ++column_num) + { + if (column_num != 0) + writeChar('\t', out); + getPort().getHeader().getByPosition(column_num).type->serializeAsText(*chunk.getColumns()[column_num], row_num, out, settings); + } + writeChar('\n', out); + } + + out.next(); + } +}; + +template +struct measure +{ + template + static typename TimeT::rep execution(F&& func, Args&&... args) + { + auto start = std::chrono::steady_clock::now(); + std::forward(func)(std::forward(args)...); + auto duration = std::chrono::duration_cast< TimeT> + (std::chrono::steady_clock::now() - start); + return duration.count(); + } +}; + +int main(int, char **) +try +{ + auto execute_chain = [](String msg, size_t start1, size_t start2, size_t start3, size_t num_threads) + { + std::cerr << msg << "\n"; + + auto source1 = std::make_shared(start1, 3, 2, 100000); + auto source2 = std::make_shared(start2, 3, 2, 100000); + auto source3 = std::make_shared(start3, 3, 2, 100000); + + auto transform1 = std::make_shared(100000); + auto transform2 = std::make_shared(100000); + auto transform3 = std::make_shared(100000); + + auto limit1 = std::make_shared(source1->getPort().getHeader(), 20, 0); + auto limit2 = std::make_shared(source2->getPort().getHeader(), 20, 0); + auto limit3 = std::make_shared(source3->getPort().getHeader(), 20, 0); + + SortDescription description = {{0, 1, 1}}; + auto merge = std::make_shared(source1->getPort().getHeader(), 3, description, 2); + auto limit_fin = std::make_shared(source1->getPort().getHeader(), 54, 0); + auto sink = std::make_shared(""); + + connect(source1->getPort(), transform1->getInputPort()); + connect(source2->getPort(), transform2->getInputPort()); + connect(source3->getPort(), transform3->getInputPort()); + + connect(transform1->getOutputPort(), limit1->getInputPort()); + connect(transform2->getOutputPort(), limit2->getInputPort()); + connect(transform3->getOutputPort(), limit3->getInputPort()); + + auto it = merge->getInputs().begin(); + connect(limit1->getOutputPort(), *(it++)); + connect(limit2->getOutputPort(), *(it++)); + connect(limit3->getOutputPort(), *(it++)); + + connect(merge->getOutputs().front(), limit_fin->getInputPort()); + connect(limit_fin->getOutputPort(), sink->getPort()); + + std::vector processors = {source1, source2, source3, + transform1, transform2, transform3, + limit1, limit2, limit3, + merge, limit_fin, sink}; +// WriteBufferFromOStream out(std::cout); +// printPipeline(processors, out); + + PipelineExecutor executor(processors); + executor.execute(num_threads); + }; + + auto even_time_single = measure<>::execution(execute_chain, "Even distribution single thread", 0, 1, 2, 1); + auto even_time_mt = measure<>::execution(execute_chain, "Even distribution multiple threads", 0, 1, 2, 4); + + auto half_time_single = measure<>::execution(execute_chain, "Half distribution single thread", 0, 31, 62, 1); + auto half_time_mt = measure<>::execution(execute_chain, "Half distribution multiple threads", 0, 31, 62, 4); + + auto ordered_time_single = measure<>::execution(execute_chain, "Ordered distribution single thread", 0, 61, 122, 1); + auto ordered_time_mt = measure<>::execution(execute_chain, "Ordered distribution multiple threads", 0, 61, 122, 4); + + std::cout << "Single Thread [0:60:3] [1:60:3] [2:60:3] time: " << even_time_single << " ms.\n"; + std::cout << "Multiple Threads [0:60:3] [1:60:3] [2:60:3] time:" << even_time_mt << " ms.\n"; + + std::cout << "Single Thread [0:60:3] [31:90:3] [62:120:3] time: " << half_time_single << " ms.\n"; + std::cout << "Multiple Threads [0:60:3] [31:90:3] [62:120:3] time: " << half_time_mt << " ms.\n"; + + std::cout << "Single Thread [0:60:3] [61:120:3] [122:180:3] time: " << ordered_time_single << " ms.\n"; + std::cout << "Multiple Threads [0:60:3] [61:120:3] [122:180:3] time: " << ordered_time_mt << " ms.\n"; + + return 0; +} +catch (...) +{ + std::cerr << getCurrentExceptionMessage(true) << '\n'; + throw; +} diff --git a/dbms/src/Storages/AlterCommands.cpp b/dbms/src/Storages/AlterCommands.cpp index 15f962f808d..7814f1a6ba0 100644 --- a/dbms/src/Storages/AlterCommands.cpp +++ b/dbms/src/Storages/AlterCommands.cpp @@ -182,7 +182,7 @@ void AlterCommand::apply(ColumnsDescription & columns_description, IndicesDescri { if (type == ADD_COLUMN) { - ColumnDescription column(column_name, data_type); + ColumnDescription column(column_name, data_type, false); if (default_expression) { column.default_desc.kind = default_kind; @@ -388,8 +388,8 @@ void AlterCommands::validate(const IStorage & table, const Context & context) column_to_command_idx[column_name] = i; /// we're creating dummy DataTypeUInt8 in order to prevent the NullPointerException in ExpressionActions - columns.add(ColumnDescription( - column_name, command.data_type ? command.data_type : std::make_shared())); + columns.add( + ColumnDescription(column_name, command.data_type ? command.data_type : std::make_shared(), false)); if (command.default_expression) { diff --git a/dbms/src/Storages/CMakeLists.txt b/dbms/src/Storages/CMakeLists.txt index 236d4d32524..ae47fba063a 100644 --- a/dbms/src/Storages/CMakeLists.txt +++ b/dbms/src/Storages/CMakeLists.txt @@ -1,5 +1,4 @@ add_subdirectory(System) -add_subdirectory(Kafka) if(ENABLE_TESTS) add_subdirectory(tests) diff --git a/dbms/src/Storages/CheckResults.h b/dbms/src/Storages/CheckResults.h new file mode 100644 index 00000000000..0f895fba3bc --- /dev/null +++ b/dbms/src/Storages/CheckResults.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +namespace DB +{ + +/// Result of CHECK TABLE query for single part of table +struct CheckResult +{ + /// Part name for merge tree or file name for simplier tables + String fs_path; + /// Does check passed + bool success = false; + /// Failure message if any + String failure_message; + + CheckResult() = default; + CheckResult(const String & fs_path_, bool success_, String failure_message_) + : fs_path(fs_path_), success(success_), failure_message(failure_message_) + {} +}; + +using CheckResults = std::vector; + +} diff --git a/dbms/src/Storages/ColumnsDescription.cpp b/dbms/src/Storages/ColumnsDescription.cpp index 55eaf1b5022..2dbe308ea57 100644 --- a/dbms/src/Storages/ColumnsDescription.cpp +++ b/dbms/src/Storages/ColumnsDescription.cpp @@ -32,6 +32,11 @@ namespace ErrorCodes extern const int CANNOT_PARSE_TEXT; } +ColumnDescription::ColumnDescription(String name_, DataTypePtr type_, bool is_virtual_) + : name(std::move(name_)), type(std::move(type_)), is_virtual(is_virtual_) +{ +} + bool ColumnDescription::operator==(const ColumnDescription & other) const { auto codec_str = [](const CompressionCodecPtr & codec_ptr) { return codec_ptr ? codec_ptr->getCodecDesc() : String(); }; @@ -115,10 +120,10 @@ void ColumnDescription::readText(ReadBuffer & buf) } -ColumnsDescription::ColumnsDescription(NamesAndTypesList ordinary) +ColumnsDescription::ColumnsDescription(NamesAndTypesList ordinary, bool all_virtuals) { for (auto & elem : ordinary) - add(ColumnDescription(std::move(elem.name), std::move(elem.type))); + add(ColumnDescription(std::move(elem.name), std::move(elem.type), all_virtuals)); } @@ -227,7 +232,7 @@ NamesAndTypesList ColumnsDescription::getOrdinary() const { NamesAndTypesList ret; for (const auto & col : columns) - if (col.default_desc.kind == ColumnDefaultKind::Default) + if (col.default_desc.kind == ColumnDefaultKind::Default && !col.is_virtual) ret.emplace_back(col.name, col.type); return ret; } @@ -250,6 +255,15 @@ NamesAndTypesList ColumnsDescription::getAliases() const return ret; } +NamesAndTypesList ColumnsDescription::getVirtuals() const +{ + NamesAndTypesList result; + for (const auto & column : columns) + if (column.is_virtual) + result.emplace_back(column.name, column.type); + return result; +} + NamesAndTypesList ColumnsDescription::getAll() const { NamesAndTypesList ret; @@ -285,7 +299,7 @@ NamesAndTypesList ColumnsDescription::getAllPhysical() const { NamesAndTypesList ret; for (const auto & col : columns) - if (col.default_desc.kind != ColumnDefaultKind::Alias) + if (col.default_desc.kind != ColumnDefaultKind::Alias && !col.is_virtual) ret.emplace_back(col.name, col.type); return ret; } @@ -294,7 +308,7 @@ Names ColumnsDescription::getNamesOfPhysical() const { Names ret; for (const auto & col : columns) - if (col.default_desc.kind != ColumnDefaultKind::Alias) + if (col.default_desc.kind != ColumnDefaultKind::Alias && !col.is_virtual) ret.emplace_back(col.name); return ret; } @@ -302,7 +316,7 @@ Names ColumnsDescription::getNamesOfPhysical() const NameAndTypePair ColumnsDescription::getPhysical(const String & column_name) const { auto it = columns.get<1>().find(column_name); - if (it == columns.get<1>().end() || it->default_desc.kind == ColumnDefaultKind::Alias) + if (it == columns.get<1>().end() || it->default_desc.kind == ColumnDefaultKind::Alias || it->is_virtual) throw Exception("There is no physical column " + column_name + " in table.", ErrorCodes::NO_SUCH_COLUMN_IN_TABLE); return NameAndTypePair(it->name, it->type); } @@ -310,7 +324,7 @@ NameAndTypePair ColumnsDescription::getPhysical(const String & column_name) cons bool ColumnsDescription::hasPhysical(const String & column_name) const { auto it = columns.get<1>().find(column_name); - return it != columns.get<1>().end() && it->default_desc.kind != ColumnDefaultKind::Alias; + return it != columns.get<1>().end() && it->default_desc.kind != ColumnDefaultKind::Alias && !it->is_virtual; } diff --git a/dbms/src/Storages/ColumnsDescription.h b/dbms/src/Storages/ColumnsDescription.h index 7ec8ed2c44f..d0d042498fa 100644 --- a/dbms/src/Storages/ColumnsDescription.h +++ b/dbms/src/Storages/ColumnsDescription.h @@ -32,9 +32,10 @@ struct ColumnDescription String comment; CompressionCodecPtr codec; ASTPtr ttl; + bool is_virtual = false; ColumnDescription() = default; - ColumnDescription(String name_, DataTypePtr type_) : name(std::move(name_)), type(std::move(type_)) {} + ColumnDescription(String name_, DataTypePtr type_, bool is_virtual_); bool operator==(const ColumnDescription & other) const; bool operator!=(const ColumnDescription & other) const { return !(*this == other); } @@ -49,7 +50,7 @@ class ColumnsDescription { public: ColumnsDescription() = default; - explicit ColumnsDescription(NamesAndTypesList ordinary_); + explicit ColumnsDescription(NamesAndTypesList ordinary_, bool all_virtuals = false); /// `after_column` can be a Nested column name; void add(ColumnDescription column, const String & after_column = String()); @@ -67,8 +68,9 @@ public: NamesAndTypesList getOrdinary() const; NamesAndTypesList getMaterialized() const; NamesAndTypesList getAliases() const; - /// ordinary + materialized + aliases. - NamesAndTypesList getAll() const; + NamesAndTypesList getVirtuals() const; + NamesAndTypesList getAllPhysical() const; /// ordinary + materialized. + NamesAndTypesList getAll() const; /// ordinary + materialized + aliases + virtuals. using ColumnTTLs = std::unordered_map; ColumnTTLs getColumnTTLs() const; @@ -87,8 +89,6 @@ public: throw Exception("Cannot modify ColumnDescription for column " + column_name + ": column name cannot be changed", ErrorCodes::LOGICAL_ERROR); } - /// ordinary + materialized. - NamesAndTypesList getAllPhysical() const; Names getNamesOfPhysical() const; bool hasPhysical(const String & column_name) const; NameAndTypePair getPhysical(const String & column_name) const; diff --git a/dbms/src/Storages/IStorage.cpp b/dbms/src/Storages/IStorage.cpp index 3d0ac164e26..687ca970311 100644 --- a/dbms/src/Storages/IStorage.cpp +++ b/dbms/src/Storages/IStorage.cpp @@ -25,28 +25,21 @@ IStorage::IStorage(ColumnsDescription columns_) setColumns(std::move(columns_)); } +IStorage::IStorage(ColumnsDescription columns_, ColumnsDescription virtuals_) : virtuals(std::move(virtuals_)) +{ + setColumns(std::move(columns_)); +} + const ColumnsDescription & IStorage::getColumns() const { return columns; } -void IStorage::setColumns(ColumnsDescription columns_) -{ - if (columns_.getOrdinary().empty()) - throw Exception("Empty list of columns passed", ErrorCodes::EMPTY_LIST_OF_COLUMNS_PASSED); - columns = std::move(columns_); -} - const IndicesDescription & IStorage::getIndices() const { return indices; } -void IStorage::setIndices(IndicesDescription indices_) -{ - indices = std::move(indices_); -} - NameAndTypePair IStorage::getColumn(const String & column_name) const { /// By default, we assume that there are no virtual columns in the storage. @@ -69,6 +62,16 @@ Block IStorage::getSampleBlock() const return res; } +Block IStorage::getSampleBlockWithVirtuals() const +{ + auto res = getSampleBlock(); + + for (const auto & column : getColumns().getVirtuals()) + res.insert({column.type->createColumn(), column.type, column.name}); + + return res; +} + Block IStorage::getSampleBlockNonMaterialized() const { Block res; @@ -266,6 +269,29 @@ void IStorage::check(const Block & block, bool need_all) const } } +void IStorage::setColumns(ColumnsDescription columns_) +{ + if (columns_.getOrdinary().empty()) + throw Exception("Empty list of columns passed", ErrorCodes::EMPTY_LIST_OF_COLUMNS_PASSED); + columns = std::move(columns_); + + for (const auto & column : virtuals) + { + if (!columns.has(column.name)) + columns.add(column); + } +} + +void IStorage::setIndices(IndicesDescription indices_) +{ + indices = std::move(indices_); +} + +bool IStorage::isVirtualColumn(const String & column_name) const +{ + return getColumns().get(column_name).is_virtual; +} + TableStructureReadLockHolder IStorage::lockStructureForShare(bool will_add_new_data, const String & query_id) { TableStructureReadLockHolder result; diff --git a/dbms/src/Storages/IStorage.h b/dbms/src/Storages/IStorage.h index f18592ebce5..9e66ee5088e 100644 --- a/dbms/src/Storages/IStorage.h +++ b/dbms/src/Storages/IStorage.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,7 @@ class IStorage : public std::enable_shared_from_this public: IStorage() = default; explicit IStorage(ColumnsDescription columns_); + IStorage(ColumnsDescription columns_, ColumnsDescription virtuals_); virtual ~IStorage() = default; IStorage(const IStorage &) = delete; @@ -60,7 +62,7 @@ public: /// The name of the table. virtual std::string getTableName() const = 0; - virtual std::string getDatabaseName() const { return {}; } // FIXME: should be an abstract method! + virtual std::string getDatabaseName() const = 0; /// Returns true if the storage receives data from a remote server or servers. virtual bool isRemote() const { return false; } @@ -82,20 +84,18 @@ public: public: /// thread-unsafe part. lockStructure must be acquired - const ColumnsDescription & getColumns() const; - void setColumns(ColumnsDescription columns_); - + const ColumnsDescription & getColumns() const; /// returns combined set of columns const IndicesDescription & getIndices() const; - void setIndices(IndicesDescription indices_); /// NOTE: these methods should include virtual columns, /// but should NOT include ALIAS columns (they are treated separately). virtual NameAndTypePair getColumn(const String & column_name) const; virtual bool hasColumn(const String & column_name) const; - Block getSampleBlock() const; - Block getSampleBlockNonMaterialized() const; - Block getSampleBlockForColumns(const Names & column_names) const; /// including virtual and alias columns. + Block getSampleBlock() const; /// ordinary + materialized. + Block getSampleBlockWithVirtuals() const; /// ordinary + materialized + virtuals. + Block getSampleBlockNonMaterialized() const; /// ordinary. + Block getSampleBlockForColumns(const Names & column_names) const; /// ordinary + materialized + aliases + virtuals. /// Verify that all the requested names are in the table and are set correctly: /// list of names is not empty and the names do not repeat. @@ -112,8 +112,17 @@ public: /// thread-unsafe part. lockStructure must be acquired /// If |need_all| is set, then checks that all the columns of the table are in the block. void check(const Block & block, bool need_all = false) const; +protected: /// still thread-unsafe part. + void setColumns(ColumnsDescription columns_); /// sets only real columns, possibly overwrites virtual ones. + void setIndices(IndicesDescription indices_); + + /// Returns whether the column is virtual - by default all columns are real. + /// Initially reserved virtual column name may be shadowed by real column. + virtual bool isVirtualColumn(const String & column_name) const; + private: - ColumnsDescription columns; + ColumnsDescription columns; /// combined real and virtual columns + const ColumnsDescription virtuals = {}; IndicesDescription indices; public: @@ -277,7 +286,7 @@ public: virtual bool mayBenefitFromIndexForIn(const ASTPtr & /* left_in_operand */, const Context & /* query_context */) const { return false; } /// Checks validity of the data - virtual bool checkData() const { throw Exception("Check query is not supported for " + getName() + " storage", ErrorCodes::NOT_IMPLEMENTED); } + virtual CheckResults checkData(const ASTPtr & /* query */, const Context & /* context */) { throw Exception("Check query is not supported for " + getName() + " storage", ErrorCodes::NOT_IMPLEMENTED); } /// Checks that table could be dropped right now /// Otherwise - throws an exception with detailed information. @@ -322,12 +331,6 @@ public: /// Returns additional columns that need to be read for FINAL to work. virtual Names getColumnsRequiredForFinal() const { return {}; } -protected: - /// Returns whether the column is virtual - by default all columns are real. - /// Initially reserved virtual column name may be shadowed by real column. - /// Returns false even for non-existent non-virtual columns. - virtual bool isVirtualColumn(const String & /* column_name */) const { return false; } - private: /// You always need to take the next three locks in this order. diff --git a/dbms/src/Storages/Kafka/CMakeLists.txt b/dbms/src/Storages/Kafka/CMakeLists.txt deleted file mode 100644 index e581b379322..00000000000 --- a/dbms/src/Storages/Kafka/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -if(USE_RDKAFKA) - include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake) - add_headers_and_sources(clickhouse_storage_kafka .) - add_library(clickhouse_storage_kafka ${clickhouse_storage_kafka_sources}) - target_link_libraries(clickhouse_storage_kafka PRIVATE clickhouse_common_io ${CPPKAFKA_LIBRARY} ${RDKAFKA_LIBRARY}) - if(NOT USE_INTERNAL_RDKAFKA_LIBRARY) - target_include_directories(clickhouse_storage_kafka SYSTEM BEFORE PRIVATE ${RDKAFKA_INCLUDE_DIR}) - endif() -endif() diff --git a/dbms/src/Storages/Kafka/KafkaBlockInputStream.cpp b/dbms/src/Storages/Kafka/KafkaBlockInputStream.cpp index 62a86d44944..5b8d80cb062 100644 --- a/dbms/src/Storages/Kafka/KafkaBlockInputStream.cpp +++ b/dbms/src/Storages/Kafka/KafkaBlockInputStream.cpp @@ -1,5 +1,7 @@ #include +#include +#include #include #include @@ -7,15 +9,17 @@ namespace DB { KafkaBlockInputStream::KafkaBlockInputStream( - StorageKafka & storage_, const Context & context_, const String & schema, size_t max_block_size_) - : storage(storage_), context(context_), max_block_size(max_block_size_) + StorageKafka & storage_, const Context & context_, const Names & columns, size_t max_block_size_) + : storage(storage_), context(context_), column_names(columns), max_block_size(max_block_size_) { context.setSetting("input_format_skip_unknown_fields", 1u); // Always skip unknown fields regardless of the context (JSON or TSKV) context.setSetting("input_format_allow_errors_ratio", 0.); - context.setSetting("input_format_allow_errors_num", storage.skip_broken); + context.setSetting("input_format_allow_errors_num", storage.skipBroken()); - if (!schema.empty()) - context.setSetting("format_schema", schema); + if (!storage.getSchemaName().empty()) + context.setSetting("format_schema", storage.getSchemaName()); + + virtual_columns = storage.getSampleBlockForColumns({"_topic", "_key", "_offset"}).cloneEmptyColumns(); } KafkaBlockInputStream::~KafkaBlockInputStream() @@ -29,6 +33,11 @@ KafkaBlockInputStream::~KafkaBlockInputStream() storage.pushBuffer(buffer); } +Block KafkaBlockInputStream::getHeader() const +{ + return storage.getSampleBlockForColumns(column_names); +} + void KafkaBlockInputStream::readPrefixImpl() { buffer = storage.tryClaimBuffer(context.getSettingsRef().queue_max_wait_ms.totalMilliseconds()); @@ -37,20 +46,49 @@ void KafkaBlockInputStream::readPrefixImpl() if (!buffer) buffer = storage.createBuffer(); - buffer->subBufferAs()->subscribe(storage.topics); + buffer->subBufferAs()->subscribe(storage.getTopics()); const auto & limits = getLimits(); const size_t poll_timeout = buffer->subBufferAs()->pollTimeout(); size_t rows_portion_size = poll_timeout ? std::min(max_block_size, limits.max_execution_time.totalMilliseconds() / poll_timeout) : max_block_size; rows_portion_size = std::max(rows_portion_size, 1ul); - auto child = FormatFactory::instance().getInput(storage.format_name, *buffer, storage.getSampleBlock(), context, max_block_size, rows_portion_size); + auto non_virtual_header = storage.getSampleBlockNonMaterialized(); /// FIXME: add materialized columns support + auto read_callback = [this] + { + const auto * sub_buffer = buffer->subBufferAs(); + virtual_columns[0]->insert(sub_buffer->currentTopic()); // "topic" + virtual_columns[1]->insert(sub_buffer->currentKey()); // "key" + virtual_columns[2]->insert(sub_buffer->currentOffset()); // "offset" + }; + + auto child = FormatFactory::instance().getInput( + storage.getFormatName(), *buffer, non_virtual_header, context, max_block_size, rows_portion_size, read_callback); child->setLimits(limits); addChild(child); broken = true; } +Block KafkaBlockInputStream::readImpl() +{ + Block block = children.back()->read(); + if (!block) + return block; + + Block virtual_block = storage.getSampleBlockForColumns({"_topic", "_key", "_offset"}).cloneWithColumns(std::move(virtual_columns)); + virtual_columns = storage.getSampleBlockForColumns({"_topic", "_key", "_offset"}).cloneEmptyColumns(); + + for (const auto & column : virtual_block.getColumnsWithTypeAndName()) + block.insert(column); + + /// FIXME: materialize MATERIALIZED columns here. + + return ConvertingBlockInputStream( + context, std::make_shared(block), getHeader(), ConvertingBlockInputStream::MatchColumnsMode::Name) + .read(); +} + void KafkaBlockInputStream::readSuffixImpl() { buffer->subBufferAs()->commit(); diff --git a/dbms/src/Storages/Kafka/KafkaBlockInputStream.h b/dbms/src/Storages/Kafka/KafkaBlockInputStream.h index f1059ca218b..a7e82034eb9 100644 --- a/dbms/src/Storages/Kafka/KafkaBlockInputStream.h +++ b/dbms/src/Storages/Kafka/KafkaBlockInputStream.h @@ -11,22 +11,24 @@ namespace DB class KafkaBlockInputStream : public IBlockInputStream { public: - KafkaBlockInputStream(StorageKafka & storage_, const Context & context_, const String & schema, size_t max_block_size_); + KafkaBlockInputStream(StorageKafka & storage_, const Context & context_, const Names & columns, size_t max_block_size_); ~KafkaBlockInputStream() override; String getName() const override { return storage.getName(); } - Block readImpl() override { return children.back()->read(); } - Block getHeader() const override { return storage.getSampleBlock(); } + Block getHeader() const override; void readPrefixImpl() override; + Block readImpl() override; void readSuffixImpl() override; private: StorageKafka & storage; Context context; + Names column_names; UInt64 max_block_size; BufferPtr buffer; + MutableColumns virtual_columns; bool broken = true, claimed = false; }; diff --git a/dbms/src/Storages/Kafka/ReadBufferFromKafkaConsumer.cpp b/dbms/src/Storages/Kafka/ReadBufferFromKafkaConsumer.cpp index 9675b29d659..fc81e38bb63 100644 --- a/dbms/src/Storages/Kafka/ReadBufferFromKafkaConsumer.cpp +++ b/dbms/src/Storages/Kafka/ReadBufferFromKafkaConsumer.cpp @@ -3,6 +3,7 @@ namespace DB { +using namespace std::chrono_literals; ReadBufferFromKafkaConsumer::ReadBufferFromKafkaConsumer( ConsumerPtr consumer_, Poco::Logger * log_, size_t max_batch_size, size_t poll_timeout_, bool intermediate_commit_) : ReadBuffer(nullptr, 0) @@ -17,7 +18,10 @@ ReadBufferFromKafkaConsumer::ReadBufferFromKafkaConsumer( ReadBufferFromKafkaConsumer::~ReadBufferFromKafkaConsumer() { + /// NOTE: see https://github.com/edenhill/librdkafka/issues/2077 consumer->unsubscribe(); + consumer->unassign(); + while (consumer->get_consumer_queue().next_event(1s)); } void ReadBufferFromKafkaConsumer::commit() @@ -45,6 +49,8 @@ void ReadBufferFromKafkaConsumer::commit() "Committed offset " << topic_part.get_offset() << " (topic: " << topic_part.get_topic() << ", partition: " << topic_part.get_partition() << ")"); } + + stalled = false; } void ReadBufferFromKafkaConsumer::subscribe(const Names & topics) @@ -53,8 +59,6 @@ void ReadBufferFromKafkaConsumer::subscribe(const Names & topics) // If we're doing a manual select then it's better to get something after a wait, then immediate nothing. if (consumer->get_subscription().empty()) { - using namespace std::chrono_literals; - consumer->pause(); // don't accidentally read any messages consumer->subscribe(topics); consumer->poll(5s); @@ -73,7 +77,7 @@ void ReadBufferFromKafkaConsumer::unsubscribe() consumer->unsubscribe(); } -/// Try to commit messages implicitly after we processed the previous batch. +/// Do commit messages implicitly after we processed the previous batch. bool ReadBufferFromKafkaConsumer::nextImpl() { /// NOTE: ReadBuffer was implemented with an immutable underlying contents in mind. @@ -86,18 +90,21 @@ bool ReadBufferFromKafkaConsumer::nextImpl() { if (intermediate_commit) commit(); - messages = consumer->poll_batch(batch_size, std::chrono::milliseconds(poll_timeout)); + + /// Don't drop old messages immediately, since we may need them for virtual columns. + auto new_messages = consumer->poll_batch(batch_size, std::chrono::milliseconds(poll_timeout)); + if (new_messages.empty()) + { + LOG_TRACE(log, "Stalled"); + stalled = true; + return false; + } + messages = std::move(new_messages); current = messages.begin(); LOG_TRACE(log, "Polled batch of " << messages.size() << " messages"); } - if (messages.empty()) - { - stalled = true; - return false; - } - if (auto err = current->get_error()) { ++current; diff --git a/dbms/src/Storages/Kafka/ReadBufferFromKafkaConsumer.h b/dbms/src/Storages/Kafka/ReadBufferFromKafkaConsumer.h index 2a473151d29..ac6011cfed0 100644 --- a/dbms/src/Storages/Kafka/ReadBufferFromKafkaConsumer.h +++ b/dbms/src/Storages/Kafka/ReadBufferFromKafkaConsumer.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -25,6 +26,11 @@ public: auto pollTimeout() { return poll_timeout; } + // Return values for the message that's being read. + String currentTopic() const { return current[-1].get_topic(); } + String currentKey() const { return current[-1].get_key(); } + auto currentOffset() const { return current[-1].get_offset(); } + private: using Messages = std::vector; diff --git a/dbms/src/Storages/Kafka/StorageKafka.cpp b/dbms/src/Storages/Kafka/StorageKafka.cpp index 81ed311eb6d..20599c7e4f8 100644 --- a/dbms/src/Storages/Kafka/StorageKafka.cpp +++ b/dbms/src/Storages/Kafka/StorageKafka.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -69,21 +71,36 @@ StorageKafka::StorageKafka( const std::string & database_name_, Context & context_, const ColumnsDescription & columns_, - const String & brokers_, const String & group_, const Names & topics_, - const String & format_name_, char row_delimiter_, const String & schema_name_, - size_t num_consumers_, UInt64 max_block_size_, size_t skip_broken_, + const String & brokers_, + const String & group_, + const Names & topics_, + const String & format_name_, + char row_delimiter_, + const String & schema_name_, + size_t num_consumers_, + UInt64 max_block_size_, + size_t skip_broken_, bool intermediate_commit_) - : IStorage{columns_}, - table_name(table_name_), database_name(database_name_), global_context(context_), - topics(global_context.getMacros()->expand(topics_)), - brokers(global_context.getMacros()->expand(brokers_)), - group(global_context.getMacros()->expand(group_)), - format_name(global_context.getMacros()->expand(format_name_)), - row_delimiter(row_delimiter_), - schema_name(global_context.getMacros()->expand(schema_name_)), - num_consumers(num_consumers_), max_block_size(max_block_size_), log(&Logger::get("StorageKafka (" + table_name_ + ")")), - semaphore(0, num_consumers_), - skip_broken(skip_broken_), intermediate_commit(intermediate_commit_) + : IStorage( + columns_, + ColumnsDescription({{"_topic", std::make_shared()}, + {"_key", std::make_shared()}, + {"_offset", std::make_shared()}}, true)) + , table_name(table_name_) + , database_name(database_name_) + , global_context(context_) + , topics(global_context.getMacros()->expand(topics_)) + , brokers(global_context.getMacros()->expand(brokers_)) + , group(global_context.getMacros()->expand(group_)) + , format_name(global_context.getMacros()->expand(format_name_)) + , row_delimiter(row_delimiter_) + , schema_name(global_context.getMacros()->expand(schema_name_)) + , num_consumers(num_consumers_) + , max_block_size(max_block_size_) + , log(&Logger::get("StorageKafka (" + table_name_ + ")")) + , semaphore(0, num_consumers_) + , skip_broken(skip_broken_) + , intermediate_commit(intermediate_commit_) { task = global_context.getSchedulePool().createTask(log->name(), [this]{ streamThread(); }); task->deactivate(); @@ -92,14 +109,12 @@ StorageKafka::StorageKafka( BlockInputStreams StorageKafka::read( const Names & column_names, - const SelectQueryInfo & /*query_info*/, + const SelectQueryInfo & /* query_info */, const Context & context, QueryProcessingStage::Enum /* processed_stage */, size_t /* max_block_size */, unsigned /* num_streams */) { - check(column_names); - if (num_created_consumers == 0) return BlockInputStreams(); @@ -113,7 +128,7 @@ BlockInputStreams StorageKafka::read( /// Use block size of 1, otherwise LIMIT won't work properly as it will buffer excess messages in the last block /// TODO: probably that leads to awful performance. /// FIXME: seems that doesn't help with extra reading and committing unprocessed messages. - streams.emplace_back(std::make_shared(*this, context, schema_name, 1)); + streams.emplace_back(std::make_shared(*this, context, column_names, 1)); } LOG_DEBUG(log, "Starting reading " << streams.size() << " streams"); @@ -161,55 +176,22 @@ void StorageKafka::shutdown() } +void StorageKafka::rename(const String & /* new_path_to_db */, const String & new_database_name, const String & new_table_name) +{ + table_name = new_table_name; + database_name = new_database_name; +} + + void StorageKafka::updateDependencies() { task->activateAndSchedule(); } -cppkafka::Configuration StorageKafka::createConsumerConfiguration() -{ - cppkafka::Configuration conf; - - LOG_TRACE(log, "Setting brokers: " << brokers); - conf.set("metadata.broker.list", brokers); - - LOG_TRACE(log, "Setting Group ID: " << group << " Client ID: clickhouse"); - conf.set("group.id", group); - - conf.set("client.id", VERSION_FULL); - - // If no offset stored for this group, read all messages from the start - conf.set("auto.offset.reset", "smallest"); - - // We manually commit offsets after a stream successfully finished - conf.set("enable.auto.commit", "false"); - - // Ignore EOF messages - conf.set("enable.partition.eof", "false"); - - // for debug logs inside rdkafka - // conf.set("debug", "consumer,cgrp,topic,fetch"); - - // Update consumer configuration from the configuration - const auto & config = global_context.getConfigRef(); - if (config.has(CONFIG_PREFIX)) - loadFromConfig(conf, config, CONFIG_PREFIX); - - // Update consumer topic-specific configuration - for (const auto & topic : topics) - { - const auto topic_config_key = CONFIG_PREFIX + "_" + topic; - if (config.has(topic_config_key)) - loadFromConfig(conf, config, topic_config_key); - } - - return conf; -} - BufferPtr StorageKafka::createBuffer() { - // Create a consumer. + // Create a consumer and subscribe to topics auto consumer = std::make_shared(createConsumerConfiguration()); // Limit the number of batched messages to allow early cancellations @@ -253,6 +235,47 @@ void StorageKafka::pushBuffer(BufferPtr buffer) semaphore.set(); } + +cppkafka::Configuration StorageKafka::createConsumerConfiguration() +{ + cppkafka::Configuration conf; + + LOG_TRACE(log, "Setting brokers: " << brokers); + conf.set("metadata.broker.list", brokers); + + LOG_TRACE(log, "Setting Group ID: " << group << " Client ID: clickhouse"); + conf.set("group.id", group); + + conf.set("client.id", VERSION_FULL); + + // If no offset stored for this group, read all messages from the start + conf.set("auto.offset.reset", "smallest"); + + // We manually commit offsets after a stream successfully finished + conf.set("enable.auto.commit", "false"); + + // Ignore EOF messages + conf.set("enable.partition.eof", "false"); + + // for debug logs inside rdkafka + // conf.set("debug", "consumer,cgrp,topic,fetch"); + + // Update consumer configuration from the configuration + const auto & config = global_context.getConfigRef(); + if (config.has(CONFIG_PREFIX)) + loadFromConfig(conf, config, CONFIG_PREFIX); + + // Update consumer topic-specific configuration + for (const auto & topic : topics) + { + const auto topic_config_key = CONFIG_PREFIX + "_" + topic; + if (config.has(topic_config_key)) + loadFromConfig(conf, config, topic_config_key); + } + + return conf; +} + bool StorageKafka::checkDependencies(const String & current_database_name, const String & current_table_name) { // Check if all dependencies are attached @@ -321,19 +344,23 @@ bool StorageKafka::streamToViews() auto insert = std::make_shared(); insert->database = database_name; insert->table = table_name; - insert->no_destination = true; // Only insert into dependent views + insert->no_destination = true; // Only insert into dependent views and expect that input blocks contain virtual columns const Settings & settings = global_context.getSettingsRef(); size_t block_size = max_block_size; if (block_size == 0) block_size = settings.max_block_size.value; + // Create a stream for each consumer and join them in a union stream + InterpreterInsertQuery interpreter{insert, global_context}; + auto block_io = interpreter.execute(); + // Create a stream for each consumer and join them in a union stream BlockInputStreams streams; streams.reserve(num_created_consumers); for (size_t i = 0; i < num_created_consumers; ++i) { - auto stream = std::make_shared(*this, global_context, schema_name, block_size); + auto stream = std::make_shared(*this, global_context, block_io.out->getHeader().getNames(), block_size); streams.emplace_back(stream); // Limit read batch to maximum block size to allow DDL @@ -350,9 +377,6 @@ bool StorageKafka::streamToViews() else in = streams[0]; - // Execute the query - InterpreterInsertQuery interpreter{insert, global_context}; - auto block_io = interpreter.execute(); copyData(*in, *block_io.out, &stream_cancelled); // Check whether the limits were applied during query execution diff --git a/dbms/src/Storages/Kafka/StorageKafka.h b/dbms/src/Storages/Kafka/StorageKafka.h index 3a40e29a03e..f9b6609def5 100644 --- a/dbms/src/Storages/Kafka/StorageKafka.h +++ b/dbms/src/Storages/Kafka/StorageKafka.h @@ -20,9 +20,6 @@ namespace DB */ class StorageKafka : public ext::shared_ptr_helper, public IStorage { - friend class KafkaBlockInputStream; - friend class KafkaBlockOutputStream; - public: std::string getName() const override { return "Kafka"; } std::string getTableName() const override { return table_name; } @@ -39,14 +36,31 @@ public: size_t max_block_size, unsigned num_streams) override; - void rename(const String & /* new_path_to_db */, const String & new_database_name, const String & new_table_name) override - { - table_name = new_table_name; - database_name = new_database_name; - } + void rename(const String & /* new_path_to_db */, const String & new_database_name, const String & new_table_name) override; void updateDependencies() override; + BufferPtr createBuffer(); + BufferPtr claimBuffer(); + BufferPtr tryClaimBuffer(long wait_ms); + void pushBuffer(BufferPtr buf); + + const auto & getTopics() const { return topics; } + const auto & getFormatName() const { return format_name; } + const auto & getSchemaName() const { return schema_name; } + const auto & skipBroken() const { return skip_broken; } + +protected: + StorageKafka( + const std::string & table_name_, + const std::string & database_name_, + Context & context_, + const ColumnsDescription & columns_, + const String & brokers_, const String & group_, const Names & topics_, + const String & format_name_, char row_delimiter_, const String & schema_name_, + size_t num_consumers_, UInt64 max_block_size_, size_t skip_broken, + bool intermediate_commit_); + private: // Configuration and state String table_name; @@ -56,18 +70,15 @@ private: const String brokers; const String group; const String format_name; - // Optional row delimiter for generating char delimited stream - // in order to make various input stream parsers happy. - char row_delimiter; + char row_delimiter; /// optional row delimiter for generating char delimited stream in order to make various input stream parsers happy. const String schema_name; - /// Total number of consumers - size_t num_consumers; - /// Maximum block size for insertion into this table - UInt64 max_block_size; - /// Number of actually created consumers. + size_t num_consumers; /// total number of consumers + UInt64 max_block_size; /// maximum block size for insertion into this table + /// Can differ from num_consumers in case of exception in startup() (or if startup() hasn't been called). /// In this case we still need to be able to shutdown() properly. - size_t num_created_consumers = 0; + size_t num_created_consumers = 0; /// number of actually created consumers. + Poco::Logger * log; // Consumer list @@ -84,25 +95,10 @@ private: std::atomic stream_cancelled{false}; cppkafka::Configuration createConsumerConfiguration(); - BufferPtr createBuffer(); - BufferPtr claimBuffer(); - BufferPtr tryClaimBuffer(long wait_ms); - void pushBuffer(BufferPtr buf); void streamThread(); bool streamToViews(); bool checkDependencies(const String & database_name, const String & table_name); - -protected: - StorageKafka( - const std::string & table_name_, - const std::string & database_name_, - Context & context_, - const ColumnsDescription & columns_, - const String & brokers_, const String & group_, const Names & topics_, - const String & format_name_, char row_delimiter_, const String & schema_name_, - size_t num_consumers_, UInt64 max_block_size_, size_t skip_broken, - bool intermediate_commit_); }; } diff --git a/dbms/src/Storages/MergeTree/BackgroundProcessingPool.cpp b/dbms/src/Storages/MergeTree/BackgroundProcessingPool.cpp index b63ffeefd5e..a883946bc78 100644 --- a/dbms/src/Storages/MergeTree/BackgroundProcessingPool.cpp +++ b/dbms/src/Storages/MergeTree/BackgroundProcessingPool.cpp @@ -206,7 +206,6 @@ void BackgroundProcessingPool::threadFunction() catch (...) { tryLogCurrentException(__PRETTY_FUNCTION__); - DNSCacheUpdater::incrementNetworkErrorEventsIfNeeded(); } if (shutdown) diff --git a/dbms/src/Storages/MergeTree/IMergedBlockOutputStream.cpp b/dbms/src/Storages/MergeTree/IMergedBlockOutputStream.cpp index 7a28df8168f..fc19fbd6792 100644 --- a/dbms/src/Storages/MergeTree/IMergedBlockOutputStream.cpp +++ b/dbms/src/Storages/MergeTree/IMergedBlockOutputStream.cpp @@ -27,13 +27,12 @@ IMergedBlockOutputStream::IMergedBlockOutputStream( , min_compress_block_size(min_compress_block_size_) , max_compress_block_size(max_compress_block_size_) , aio_threshold(aio_threshold_) - , marks_file_extension(storage.index_granularity_info.marks_file_extension) - , mark_size_in_bytes(storage.index_granularity_info.mark_size_in_bytes) + , marks_file_extension(storage.canUseAdaptiveGranularity() ? getAdaptiveMrkExtension() : getNonAdaptiveMrkExtension()) , blocks_are_granules_size(blocks_are_granules_size_) , index_granularity(index_granularity_) , compute_granularity(index_granularity.empty()) , codec(std::move(codec_)) - , with_final_mark(storage.settings.write_final_mark && storage.index_granularity_info.is_adaptive) + , with_final_mark(storage.settings.write_final_mark && storage.canUseAdaptiveGranularity()) { if (blocks_are_granules_size && !index_granularity.empty()) throw Exception("Can't take information about index granularity from blocks, when non empty index_granularity array specified", ErrorCodes::LOGICAL_ERROR); @@ -99,11 +98,12 @@ void fillIndexGranularityImpl( size_t fixed_index_granularity_rows, bool blocks_are_granules, size_t index_offset, - MergeTreeIndexGranularity & index_granularity) + MergeTreeIndexGranularity & index_granularity, + bool can_use_adaptive_index_granularity) { size_t rows_in_block = block.rows(); size_t index_granularity_for_block; - if (index_granularity_bytes == 0) + if (!can_use_adaptive_index_granularity) index_granularity_for_block = fixed_index_granularity_rows; else { @@ -135,11 +135,12 @@ void IMergedBlockOutputStream::fillIndexGranularity(const Block & block) { fillIndexGranularityImpl( block, - storage.index_granularity_info.index_granularity_bytes, - storage.index_granularity_info.fixed_index_granularity, + storage.settings.index_granularity_bytes, + storage.settings.index_granularity, blocks_are_granules_size, index_offset, - index_granularity); + index_granularity, + storage.canUseAdaptiveGranularity()); } void IMergedBlockOutputStream::writeSingleMark( @@ -170,7 +171,7 @@ void IMergedBlockOutputStream::writeSingleMark( writeIntBinary(stream.plain_hashing.count(), stream.marks); writeIntBinary(stream.compressed.offset(), stream.marks); - if (storage.index_granularity_info.is_adaptive) + if (storage.canUseAdaptiveGranularity()) writeIntBinary(number_of_rows, stream.marks); }, path); } diff --git a/dbms/src/Storages/MergeTree/IMergedBlockOutputStream.h b/dbms/src/Storages/MergeTree/IMergedBlockOutputStream.h index 995e7567fa9..b9d083f3a19 100644 --- a/dbms/src/Storages/MergeTree/IMergedBlockOutputStream.h +++ b/dbms/src/Storages/MergeTree/IMergedBlockOutputStream.h @@ -134,7 +134,6 @@ protected: size_t current_mark = 0; const std::string marks_file_extension; - const size_t mark_size_in_bytes; const bool blocks_are_granules_size; MergeTreeIndexGranularity index_granularity; diff --git a/dbms/src/Storages/MergeTree/KeyCondition.cpp b/dbms/src/Storages/MergeTree/KeyCondition.cpp index 400feaad860..442bab74382 100644 --- a/dbms/src/Storages/MergeTree/KeyCondition.cpp +++ b/dbms/src/Storages/MergeTree/KeyCondition.cpp @@ -191,6 +191,27 @@ const KeyCondition::AtomMap KeyCondition::atom_map String right_bound = firstStringThatIsGreaterThanAllStringsWithPrefix(prefix); + out.function = RPNElement::FUNCTION_IN_RANGE; + out.range = !right_bound.empty() + ? Range(prefix, true, right_bound, false) + : Range::createLeftBounded(prefix, true); + + return true; + } + }, + { + "startsWith", + [] (RPNElement & out, const Field & value) + { + if (value.getType() != Field::Types::String) + return false; + + String prefix = value.get(); + if (prefix.empty()) + return false; + + String right_bound = firstStringThatIsGreaterThanAllStringsWithPrefix(prefix); + out.function = RPNElement::FUNCTION_IN_RANGE; out.range = !right_bound.empty() ? Range(prefix, true, right_bound, false) @@ -334,7 +355,7 @@ bool KeyCondition::getConstant(const ASTPtr & expr, Block & block_with_constants out_type = block_with_constants.getByName(column_name).type; return true; } - else if (block_with_constants.has(column_name) && block_with_constants.getByName(column_name).column->isColumnConst()) + else if (block_with_constants.has(column_name) && isColumnConst(*block_with_constants.getByName(column_name).column)) { /// An expression which is dependent on constants only const auto & expr_info = block_with_constants.getByName(column_name); diff --git a/dbms/src/Storages/MergeTree/MergeTreeBaseSelectBlockInputStream.cpp b/dbms/src/Storages/MergeTree/MergeTreeBaseSelectBlockInputStream.cpp index 9f4d4ae715c..ad953357edb 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeBaseSelectBlockInputStream.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeBaseSelectBlockInputStream.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include diff --git a/dbms/src/Storages/MergeTree/MergeTreeBlockReadUtils.h b/dbms/src/Storages/MergeTree/MergeTreeBlockReadUtils.h index 0ce69ebac84..cee344b1cef 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeBlockReadUtils.h +++ b/dbms/src/Storages/MergeTree/MergeTreeBlockReadUtils.h @@ -99,12 +99,6 @@ struct MergeTreeBlockSizePredictor : 0; } - /// Predicts what number of marks should be read to exhaust byte quota - inline size_t estimateNumMarks(size_t bytes_quota, size_t index_granularity) const - { - return (estimateNumRows(bytes_quota) + index_granularity / 2) / index_granularity; - } - inline void updateFilteredRowsRation(size_t rows_was_read, size_t rows_was_filtered, double decay = DECAY()) { double alpha = std::pow(1. - decay, rows_was_read); diff --git a/dbms/src/Storages/MergeTree/MergeTreeData.cpp b/dbms/src/Storages/MergeTree/MergeTreeData.cpp index b142ceeec22..d1e9e470e57 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeData.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeData.cpp @@ -107,7 +107,6 @@ MergeTreeData::MergeTreeData( bool attach, BrokenPartCallback broken_part_callback_) : global_context(context_), - index_granularity_info(settings_), merging_params(merging_params_), settings(settings_), partition_by_ast(partition_by_ast_), @@ -199,27 +198,6 @@ MergeTreeData::MergeTreeData( "MergeTree data format version on disk doesn't support custom partitioning", ErrorCodes::METADATA_MISMATCH); } - -} - - -MergeTreeData::IndexGranularityInfo::IndexGranularityInfo(const MergeTreeSettings & settings) - : fixed_index_granularity(settings.index_granularity) - , index_granularity_bytes(settings.index_granularity_bytes) -{ - /// Granularity is fixed - if (index_granularity_bytes == 0) - { - is_adaptive = false; - mark_size_in_bytes = sizeof(UInt64) * 2; - marks_file_extension = ".mrk"; - } - else - { - is_adaptive = true; - mark_size_in_bytes = sizeof(UInt64) * 3; - marks_file_extension = ".mrk2"; - } } @@ -243,7 +221,7 @@ static void checkKeyExpression(const ExpressionActions & expr, const Block & sam for (const ColumnWithTypeAndName & element : sample_block) { const ColumnPtr & column = element.column; - if (column && (column->isColumnConst() || column->isDummy())) + if (column && (isColumnConst(*column) || column->isDummy())) throw Exception{key_name + " key cannot contain constants", ErrorCodes::ILLEGAL_COLUMN}; if (element.type->isNullable()) @@ -765,6 +743,7 @@ void MergeTreeData::loadDataParts(bool skip_sanity_checks) auto lock = lockParts(); data_parts_indexes.clear(); + bool has_adaptive_parts = false, has_non_adaptive_parts = false; for (const String & file_name : part_file_names) { MergeTreePartInfo part_info; @@ -849,6 +828,10 @@ void MergeTreeData::loadDataParts(bool skip_sanity_checks) continue; } + if (!part->index_granularity_info.is_adaptive) + has_non_adaptive_parts = true; + else + has_adaptive_parts = true; part->modification_time = Poco::File(full_path + file_name).getLastModified().epochTime(); /// Assume that all parts are Committed, covered parts will be detected and marked as Outdated later @@ -858,6 +841,11 @@ void MergeTreeData::loadDataParts(bool skip_sanity_checks) throw Exception("Part " + part->name + " already exists", ErrorCodes::DUPLICATE_DATA_PART); } + if (has_non_adaptive_parts && has_adaptive_parts && !settings.enable_mixed_granularity_parts) + throw Exception("Table contains parts with adaptive and non adaptive marks, but `setting enable_mixed_granularity_parts` is disabled", ErrorCodes::LOGICAL_ERROR); + + has_non_adaptive_index_granularity_parts = has_non_adaptive_parts; + if (suspicious_broken_parts > settings.max_suspicious_broken_parts && !skip_sanity_checks) throw Exception("Suspiciously many (" + toString(suspicious_broken_parts) + ") broken parts to remove.", ErrorCodes::TOO_MANY_UNEXPECTED_DATA_PARTS); @@ -1289,6 +1277,11 @@ void MergeTreeData::createConvertExpression(const DataPartPtr & part, const Name out_expression = nullptr; out_rename_map = {}; out_force_update_metadata = false; + String part_mrk_file_extension; + if (part) + part_mrk_file_extension = part->index_granularity_info.marks_file_extension; + else + part_mrk_file_extension = settings.index_granularity_bytes == 0 ? getNonAdaptiveMrkExtension() : getAdaptiveMrkExtension(); using NameToType = std::map; NameToType new_types; @@ -1309,7 +1302,7 @@ void MergeTreeData::createConvertExpression(const DataPartPtr & part, const Name if (!new_indices_set.count(index.name)) { out_rename_map["skp_idx_" + index.name + ".idx"] = ""; - out_rename_map["skp_idx_" + index.name + index_granularity_info.marks_file_extension] = ""; + out_rename_map["skp_idx_" + index.name + part_mrk_file_extension] = ""; } } @@ -1338,7 +1331,7 @@ void MergeTreeData::createConvertExpression(const DataPartPtr & part, const Name if (--stream_counts[file_name] == 0) { out_rename_map[file_name + ".bin"] = ""; - out_rename_map[file_name + index_granularity_info.marks_file_extension] = ""; + out_rename_map[file_name + part_mrk_file_extension] = ""; } }, {}); } @@ -1413,7 +1406,7 @@ void MergeTreeData::createConvertExpression(const DataPartPtr & part, const Name String temporary_file_name = IDataType::getFileNameForStream(temporary_column_name, substream_path); out_rename_map[temporary_file_name + ".bin"] = original_file_name + ".bin"; - out_rename_map[temporary_file_name + index_granularity_info.marks_file_extension] = original_file_name + index_granularity_info.marks_file_extension; + out_rename_map[temporary_file_name + part_mrk_file_extension] = original_file_name + part_mrk_file_extension; }, {}); } @@ -2841,4 +2834,16 @@ void MergeTreeData::freezePartitionsByMatcher(MatcherFn matcher, const String & LOG_DEBUG(log, "Freezed " << parts_processed << " parts"); } +bool MergeTreeData::canReplacePartition(const DataPartPtr & src_part) const +{ + if (!settings.enable_mixed_granularity_parts || settings.index_granularity_bytes == 0) + { + if (!canUseAdaptiveGranularity() && src_part->index_granularity_info.is_adaptive) + return false; + if (canUseAdaptiveGranularity() && !src_part->index_granularity_info.is_adaptive) + return false; + } + return true; +} + } diff --git a/dbms/src/Storages/MergeTree/MergeTreeData.h b/dbms/src/Storages/MergeTree/MergeTreeData.h index 9b543f86b75..2ebddb886f6 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeData.h +++ b/dbms/src/Storages/MergeTree/MergeTreeData.h @@ -285,33 +285,6 @@ public: String getModeName() const; }; - /// Meta information about index granularity - struct IndexGranularityInfo - { - /// Marks file extension '.mrk' or '.mrk2' - String marks_file_extension; - - /// Size of one mark in file two or three size_t numbers - UInt8 mark_size_in_bytes; - - /// Is stride in rows between marks non fixed? - bool is_adaptive; - - /// Fixed size in rows of one granule if index_granularity_bytes is zero - size_t fixed_index_granularity; - - /// Approximate bytes size of one granule - size_t index_granularity_bytes; - - IndexGranularityInfo(const MergeTreeSettings & settings); - - String getMarksFilePath(const String & column_path) const - { - return column_path + marks_file_extension; - } - }; - - /// Attach the table corresponding to the directory in full_path (must end with /), with the given columns. /// Correctness of names and paths is not checked. /// @@ -601,10 +574,16 @@ public: virtual std::vector getMutationsStatus() const = 0; + bool canUseAdaptiveGranularity() const + { + return settings.index_granularity_bytes != 0 && + (settings.enable_mixed_granularity_parts || !has_non_adaptive_index_granularity_parts); + } + + MergeTreeDataFormatVersion format_version; Context global_context; - IndexGranularityInfo index_granularity_info; /// Merging params - what additional actions to perform during merge. const MergingParams merging_params; @@ -659,6 +638,8 @@ public: /// For generating names of temporary parts during insertion. SimpleIncrement insert_increment; + bool has_non_adaptive_index_granularity_parts = false; + protected: friend struct MergeTreeDataPart; friend class MergeTreeDataMergerMutator; @@ -818,6 +799,9 @@ protected: /// Common part for |freezePartition()| and |freezeAll()|. using MatcherFn = std::function; void freezePartitionsByMatcher(MatcherFn matcher, const String & with_name, const Context & context); + + bool canReplacePartition(const DataPartPtr & data_part) const; + }; } diff --git a/dbms/src/Storages/MergeTree/MergeTreeDataMergerMutator.cpp b/dbms/src/Storages/MergeTree/MergeTreeDataMergerMutator.cpp index 705c1ed3525..e30bbdcda0b 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeDataMergerMutator.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeDataMergerMutator.cpp @@ -984,13 +984,14 @@ MergeTreeData::MutableDataPartPtr MergeTreeDataMergerMutator::mutatePartToTempor } NameSet files_to_skip = {"checksums.txt", "columns.txt"}; + auto mrk_extension = data.settings.index_granularity_bytes ? getAdaptiveMrkExtension() : getNonAdaptiveMrkExtension(); for (const auto & entry : in_header) { IDataType::StreamCallback callback = [&](const IDataType::SubstreamPath & substream_path) { String stream_name = IDataType::getFileNameForStream(entry.name, substream_path); files_to_skip.insert(stream_name + ".bin"); - files_to_skip.insert(stream_name + data.index_granularity_info.marks_file_extension); + files_to_skip.insert(stream_name + mrk_extension); }; IDataType::SubstreamPath stream_path; diff --git a/dbms/src/Storages/MergeTree/MergeTreeDataPart.cpp b/dbms/src/Storages/MergeTree/MergeTreeDataPart.cpp index b3f2e3f86b2..fc4c5fef130 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeDataPart.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeDataPart.cpp @@ -138,6 +138,7 @@ MergeTreeDataPart::MergeTreeDataPart(MergeTreeData & storage_, const String & na : storage(storage_) , name(name_) , info(MergeTreePartInfo::fromPartName(name_, storage.format_version)) + , index_granularity_info(storage) { } @@ -145,6 +146,7 @@ MergeTreeDataPart::MergeTreeDataPart(const MergeTreeData & storage_, const Strin : storage(storage_) , name(name_) , info(info_) + , index_granularity_info(storage) { } @@ -172,7 +174,7 @@ MergeTreeDataPart::ColumnSize MergeTreeDataPart::getColumnSizeImpl( size.data_uncompressed += bin_checksum->second.uncompressed_size; } - auto mrk_checksum = checksums.files.find(file_name + storage.index_granularity_info.marks_file_extension); + auto mrk_checksum = checksums.files.find(file_name + index_granularity_info.marks_file_extension); if (mrk_checksum != checksums.files.end()) size.marks += mrk_checksum->second.file_size; }, {}); @@ -536,22 +538,25 @@ void MergeTreeDataPart::loadColumnsChecksumsIndexes(bool require_columns_checksu void MergeTreeDataPart::loadIndexGranularity() { + + String full_path = getFullPath(); + index_granularity_info.changeGranularityIfRequired(full_path); + if (columns.empty()) throw Exception("No columns in part " + name, ErrorCodes::NO_FILE_IN_DATA_PART); - const auto & granularity_info = storage.index_granularity_info; /// We can use any column, it doesn't matter - std::string marks_file_path = granularity_info.getMarksFilePath(getFullPath() + escapeForFileName(columns.front().name)); + std::string marks_file_path = index_granularity_info.getMarksFilePath(full_path + escapeForFileName(columns.front().name)); if (!Poco::File(marks_file_path).exists()) throw Exception("Marks file '" + marks_file_path + "' doesn't exist", ErrorCodes::NO_FILE_IN_DATA_PART); size_t marks_file_size = Poco::File(marks_file_path).getSize(); /// old version of marks with static index granularity - if (!granularity_info.is_adaptive) + if (!index_granularity_info.is_adaptive) { - size_t marks_count = marks_file_size / granularity_info.mark_size_in_bytes; - index_granularity.resizeWithFixedGranularity(marks_count, granularity_info.fixed_index_granularity); /// all the same + size_t marks_count = marks_file_size / index_granularity_info.mark_size_in_bytes; + index_granularity.resizeWithFixedGranularity(marks_count, index_granularity_info.fixed_index_granularity); /// all the same } else { @@ -563,7 +568,7 @@ void MergeTreeDataPart::loadIndexGranularity() readIntBinary(granularity, buffer); index_granularity.appendMark(granularity); } - if (index_granularity.getMarksCount() * granularity_info.mark_size_in_bytes != marks_file_size) + if (index_granularity.getMarksCount() * index_granularity_info.mark_size_in_bytes != marks_file_size) throw Exception("Cannot read all marks from file " + marks_file_path, ErrorCodes::CANNOT_READ_ALL_DATA); } index_granularity.setInitialized(); @@ -702,7 +707,7 @@ void MergeTreeDataPart::loadRowsCount() ErrorCodes::LOGICAL_ERROR); } - size_t last_mark_index_granularity = index_granularity.getLastMarkRows(); + size_t last_mark_index_granularity = index_granularity.getLastNonFinalMarkRows(); size_t rows_approx = index_granularity.getTotalRows(); if (!(rows_count <= rows_approx && rows_approx < rows_count + last_mark_index_granularity)) throw Exception( @@ -809,7 +814,7 @@ void MergeTreeDataPart::checkConsistency(bool require_part_metadata) name_type.type->enumerateStreams([&](const IDataType::SubstreamPath & substream_path) { String file_name = IDataType::getFileNameForStream(name_type.name, substream_path); - String mrk_file_name = file_name + storage.index_granularity_info.marks_file_extension; + String mrk_file_name = file_name + index_granularity_info.marks_file_extension; String bin_file_name = file_name + ".bin"; if (!checksums.files.count(mrk_file_name)) throw Exception("No " + mrk_file_name + " file checksum for column " + name_type.name + " in part " + path, @@ -873,7 +878,7 @@ void MergeTreeDataPart::checkConsistency(bool require_part_metadata) { name_type.type->enumerateStreams([&](const IDataType::SubstreamPath & substream_path) { - Poco::File file(IDataType::getFileNameForStream(name_type.name, substream_path) + storage.index_granularity_info.marks_file_extension); + Poco::File file(IDataType::getFileNameForStream(name_type.name, substream_path) + index_granularity_info.marks_file_extension); /// Missing file is Ok for case when new column was added. if (file.exists()) @@ -904,7 +909,7 @@ bool MergeTreeDataPart::hasColumnFiles(const String & column_name, const IDataTy String file_name = IDataType::getFileNameForStream(column_name, substream_path); auto bin_checksum = checksums.files.find(file_name + ".bin"); - auto mrk_checksum = checksums.files.find(file_name + storage.index_granularity_info.marks_file_extension); + auto mrk_checksum = checksums.files.find(file_name + index_granularity_info.marks_file_extension); if (bin_checksum == checksums.files.end() || mrk_checksum == checksums.files.end()) res = false; diff --git a/dbms/src/Storages/MergeTree/MergeTreeDataPart.h b/dbms/src/Storages/MergeTree/MergeTreeDataPart.h index 921fea6ccaa..f775e5bc085 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeDataPart.h +++ b/dbms/src/Storages/MergeTree/MergeTreeDataPart.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -246,6 +247,8 @@ struct MergeTreeDataPart */ mutable std::mutex alter_mutex; + MergeTreeIndexGranularityInfo index_granularity_info; + ~MergeTreeDataPart(); /// Calculate the total size of the entire directory with all the files diff --git a/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp b/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp index 2131067df28..bb2e7827aa4 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp @@ -518,7 +518,7 @@ BlockInputStreams MergeTreeDataSelectExecutor::readFromParts( RangesInDataParts parts_with_ranges; - std::vector> useful_indices; + std::vector> useful_indices; for (const auto & index : data.skip_indices) { auto condition = index->createIndexCondition(query_info, context); @@ -623,18 +623,13 @@ namespace size_t roundRowsOrBytesToMarks( size_t rows_setting, size_t bytes_setting, - const MergeTreeData::IndexGranularityInfo & granularity_info) + size_t rows_granularity, + size_t bytes_granularity) { - if (!granularity_info.is_adaptive) - { - size_t fixed_index_granularity = granularity_info.fixed_index_granularity; - return (rows_setting + fixed_index_granularity - 1) / fixed_index_granularity; - } + if (bytes_granularity == 0) + return (rows_setting + rows_granularity - 1) / rows_granularity; else - { - size_t index_granularity_bytes = granularity_info.index_granularity_bytes; - return (bytes_setting + index_granularity_bytes - 1) / index_granularity_bytes; - } + return (bytes_setting + bytes_granularity - 1) / bytes_granularity; } } @@ -650,20 +645,13 @@ BlockInputStreams MergeTreeDataSelectExecutor::spreadMarkRangesAmongStreams( const Names & virt_columns, const Settings & settings) const { - const size_t max_marks_to_use_cache = roundRowsOrBytesToMarks( - settings.merge_tree_max_rows_to_use_cache, - settings.merge_tree_max_bytes_to_use_cache, - data.index_granularity_info); - - const size_t min_marks_for_concurrent_read = roundRowsOrBytesToMarks( - settings.merge_tree_min_rows_for_concurrent_read, - settings.merge_tree_min_bytes_for_concurrent_read, - data.index_granularity_info); /// Count marks for each part. std::vector sum_marks_in_parts(parts.size()); size_t sum_marks = 0; size_t total_rows = 0; + + size_t adaptive_parts = 0; for (size_t i = 0; i < parts.size(); ++i) { total_rows += parts[i].getRowsCount(); @@ -674,8 +662,26 @@ BlockInputStreams MergeTreeDataSelectExecutor::spreadMarkRangesAmongStreams( sum_marks_in_parts[i] += range.end - range.begin; sum_marks += sum_marks_in_parts[i]; + if (parts[i].data_part->index_granularity_info.is_adaptive) + adaptive_parts++; } + size_t index_granularity_bytes = 0; + if (adaptive_parts > parts.size() / 2) + index_granularity_bytes = data.settings.index_granularity_bytes; + + const size_t max_marks_to_use_cache = roundRowsOrBytesToMarks( + settings.merge_tree_max_rows_to_use_cache, + settings.merge_tree_max_bytes_to_use_cache, + data.settings.index_granularity, + index_granularity_bytes); + + const size_t min_marks_for_concurrent_read = roundRowsOrBytesToMarks( + settings.merge_tree_min_rows_for_concurrent_read, + settings.merge_tree_min_bytes_for_concurrent_read, + data.settings.index_granularity, + index_granularity_bytes); + if (sum_marks > max_marks_to_use_cache) use_uncompressed_cache = false; @@ -798,15 +804,27 @@ BlockInputStreams MergeTreeDataSelectExecutor::spreadMarkRangesAmongStreamsFinal const Names & virt_columns, const Settings & settings) const { + + size_t sum_marks = 0; + size_t adaptive_parts = 0; + for (size_t i = 0; i < parts.size(); ++i) + { + for (size_t j = 0; j < parts[i].ranges.size(); ++j) + sum_marks += parts[i].ranges[j].end - parts[i].ranges[j].begin; + + if (parts[i].data_part->index_granularity_info.is_adaptive) + adaptive_parts++; + } + + size_t index_granularity_bytes = 0; + if (adaptive_parts >= parts.size() / 2) + index_granularity_bytes = data.settings.index_granularity_bytes; + const size_t max_marks_to_use_cache = roundRowsOrBytesToMarks( settings.merge_tree_max_rows_to_use_cache, settings.merge_tree_max_bytes_to_use_cache, - data.index_granularity_info); - - size_t sum_marks = 0; - for (size_t i = 0; i < parts.size(); ++i) - for (size_t j = 0; j < parts[i].ranges.size(); ++j) - sum_marks += parts[i].ranges[j].end - parts[i].ranges[j].begin; + data.settings.index_granularity, + index_granularity_bytes); if (sum_marks > max_marks_to_use_cache) use_uncompressed_cache = false; @@ -828,6 +846,7 @@ BlockInputStreams MergeTreeDataSelectExecutor::spreadMarkRangesAmongStreamsFinal to_merge.emplace_back(std::make_shared(source_stream, data.sorting_key_expr)); } + Names sort_columns = data.sorting_key_columns; SortDescription sort_description; size_t sort_columns_size = sort_columns.size(); @@ -926,7 +945,8 @@ MarkRanges MergeTreeDataSelectExecutor::markRangesFromPKRange( size_t min_marks_for_seek = roundRowsOrBytesToMarks( settings.merge_tree_min_rows_for_seek, settings.merge_tree_min_bytes_for_seek, - data.index_granularity_info); + part->index_granularity_info.fixed_index_granularity, + part->index_granularity_info.index_granularity_bytes); /** There will always be disjoint suspicious segments on the stack, the leftmost one at the top (back). * At each step, take the left segment and check if it fits. @@ -998,7 +1018,7 @@ MarkRanges MergeTreeDataSelectExecutor::markRangesFromPKRange( MarkRanges MergeTreeDataSelectExecutor::filterMarksUsingIndex( MergeTreeIndexPtr index, - IndexConditionPtr condition, + MergeTreeIndexConditionPtr condition, MergeTreeData::DataPartPtr part, const MarkRanges & ranges, const Settings & settings) const @@ -1012,7 +1032,8 @@ MarkRanges MergeTreeDataSelectExecutor::filterMarksUsingIndex( const size_t min_marks_for_seek = roundRowsOrBytesToMarks( settings.merge_tree_min_rows_for_seek, settings.merge_tree_min_bytes_for_seek, - data.index_granularity_info); + part->index_granularity_info.index_granularity_bytes, + part->index_granularity_info.fixed_index_granularity); size_t granules_dropped = 0; diff --git a/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.h b/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.h index a949d593904..d38d00d055b 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.h +++ b/dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.h @@ -84,7 +84,7 @@ private: MarkRanges filterMarksUsingIndex( MergeTreeIndexPtr index, - IndexConditionPtr condition, + MergeTreeIndexConditionPtr condition, MergeTreeData::DataPartPtr part, const MarkRanges & ranges, const Settings & settings) const; diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexAggregatorBloomFilter.cpp b/dbms/src/Storages/MergeTree/MergeTreeIndexAggregatorBloomFilter.cpp new file mode 100644 index 00000000000..760721b5f3c --- /dev/null +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexAggregatorBloomFilter.cpp @@ -0,0 +1,62 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int LOGICAL_ERROR; + extern const int ILLEGAL_COLUMN; +} + +MergeTreeIndexAggregatorBloomFilter::MergeTreeIndexAggregatorBloomFilter( + size_t bits_per_row_, size_t hash_functions_, const Names & columns_name_) + : bits_per_row(bits_per_row_), hash_functions(hash_functions_), index_columns_name(columns_name_) +{ +} + +bool MergeTreeIndexAggregatorBloomFilter::empty() const +{ + return !total_rows; +} + +MergeTreeIndexGranulePtr MergeTreeIndexAggregatorBloomFilter::getGranuleAndReset() +{ + const auto granule = std::make_shared(bits_per_row, hash_functions, total_rows, granule_index_blocks); + total_rows = 0; + granule_index_blocks.clear(); + return granule; +} + +void MergeTreeIndexAggregatorBloomFilter::update(const Block & block, size_t * pos, size_t limit) +{ + if (*pos >= block.rows()) + throw Exception("The provided position is not less than the number of block rows. Position: " + toString(*pos) + ", Block rows: " + + toString(block.rows()) + ".", ErrorCodes::LOGICAL_ERROR); + + Block granule_index_block; + size_t max_read_rows = std::min(block.rows() - *pos, limit); + + for (size_t index = 0; index < index_columns_name.size(); ++index) + { + const auto & column_and_type = block.getByName(index_columns_name[index]); + const auto & index_column = BloomFilterHash::hashWithColumn(column_and_type.type, column_and_type.column, *pos, max_read_rows); + + granule_index_block.insert({std::move(index_column), std::make_shared(), column_and_type.name}); + } + + *pos += max_read_rows; + total_rows += max_read_rows; + granule_index_blocks.push_back(granule_index_block); +} + +} diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexAggregatorBloomFilter.h b/dbms/src/Storages/MergeTree/MergeTreeIndexAggregatorBloomFilter.h new file mode 100644 index 00000000000..ebbe9865313 --- /dev/null +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexAggregatorBloomFilter.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +namespace DB +{ + +class MergeTreeIndexAggregatorBloomFilter : public IMergeTreeIndexAggregator +{ +public: + MergeTreeIndexAggregatorBloomFilter(size_t bits_per_row_, size_t hash_functions_, const Names & columns_name_); + + bool empty() const override; + + MergeTreeIndexGranulePtr getGranuleAndReset() override; + + void update(const Block & block, size_t * pos, size_t limit) override; + +private: + size_t bits_per_row; + size_t hash_functions; + const Names index_columns_name; + + size_t total_rows = 0; + Blocks granule_index_blocks; +}; + +} diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexBloomFilter.cpp b/dbms/src/Storages/MergeTree/MergeTreeIndexBloomFilter.cpp new file mode 100644 index 00000000000..b86da56649d --- /dev/null +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexBloomFilter.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int LOGICAL_ERROR; + extern const int INCORRECT_QUERY; +} + +MergeTreeIndexBloomFilter::MergeTreeIndexBloomFilter( + const String & name_, const ExpressionActionsPtr & expr_, const Names & columns_, const DataTypes & data_types_, const Block & header_, + size_t granularity_, size_t bits_per_row_, size_t hash_functions_) + : IMergeTreeIndex(name_, expr_, columns_, data_types_, header_, granularity_), bits_per_row(bits_per_row_), + hash_functions(hash_functions_) +{ +} + +MergeTreeIndexGranulePtr MergeTreeIndexBloomFilter::createIndexGranule() const +{ + return std::make_shared(bits_per_row, hash_functions, columns.size()); +} + +bool MergeTreeIndexBloomFilter::mayBenefitFromIndexForIn(const ASTPtr & node) const +{ + const String & column_name = node->getColumnName(); + + for (const auto & name : columns) + if (column_name == name) + return true; + + if (const auto * func = typeid_cast(node.get())) + { + for (const auto & children : func->arguments->children) + if (mayBenefitFromIndexForIn(children)) + return true; + } + + return false; +} + +MergeTreeIndexAggregatorPtr MergeTreeIndexBloomFilter::createIndexAggregator() const +{ + return std::make_shared(bits_per_row, hash_functions, columns); +} + +MergeTreeIndexConditionPtr MergeTreeIndexBloomFilter::createIndexCondition(const SelectQueryInfo & query_info, const Context & context) const +{ + return std::make_shared(query_info, context, header, hash_functions); +} + +static void assertIndexColumnsType(const Block & header) +{ + if (!header || !header.columns()) + throw Exception("Index must have columns.", ErrorCodes::INCORRECT_QUERY); + + const DataTypes & columns_data_types = header.getDataTypes(); + + for (size_t index = 0; index < columns_data_types.size(); ++index) + { + WhichDataType which(columns_data_types[index]); + + if (!which.isUInt() && !which.isInt() && !which.isString() && !which.isFixedString() && !which.isFloat() && + !which.isDateOrDateTime() && !which.isEnum()) + throw Exception("Unexpected type " + columns_data_types[index]->getName() + " of bloom filter index.", + ErrorCodes::ILLEGAL_COLUMN); + } +} + +std::unique_ptr bloomFilterIndexCreatorNew( + const NamesAndTypesList & columns, std::shared_ptr node, const Context & context) +{ + if (node->name.empty()) + throw Exception("Index must have unique name.", ErrorCodes::INCORRECT_QUERY); + + ASTPtr expr_list = MergeTreeData::extractKeyExpressionList(node->expr->clone()); + + auto syntax = SyntaxAnalyzer(context, {}).analyze(expr_list, columns); + auto index_expr = ExpressionAnalyzer(expr_list, syntax, context).getActions(false); + auto index_sample = ExpressionAnalyzer(expr_list, syntax, context).getActions(true)->getSampleBlock(); + + assertIndexColumnsType(index_sample); + + double max_conflict_probability = 0.025; + if (node->type->arguments && !node->type->arguments->children.empty()) + max_conflict_probability = typeid_cast(*node->type->arguments->children[0]).value.get(); + + const auto & bits_per_row_and_size_of_hash_functions = BloomFilterHash::calculationBestPractices(max_conflict_probability); + + return std::make_unique( + node->name, std::move(index_expr), index_sample.getNames(), index_sample.getDataTypes(), index_sample, node->granularity, + bits_per_row_and_size_of_hash_functions.first, bits_per_row_and_size_of_hash_functions.second); +} + +} diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexBloomFilter.h b/dbms/src/Storages/MergeTree/MergeTreeIndexBloomFilter.h new file mode 100644 index 00000000000..2b89b9bddfa --- /dev/null +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexBloomFilter.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include + +namespace DB +{ + +class MergeTreeIndexBloomFilter : public IMergeTreeIndex +{ +public: + MergeTreeIndexBloomFilter( + const String & name_, const ExpressionActionsPtr & expr_, const Names & columns_, const DataTypes & data_types_, + const Block & header_, size_t granularity_, size_t bits_per_row_, size_t hash_functions_); + + MergeTreeIndexGranulePtr createIndexGranule() const override; + + MergeTreeIndexAggregatorPtr createIndexAggregator() const override; + + MergeTreeIndexConditionPtr createIndexCondition(const SelectQueryInfo & query_info, const Context & context) const override; + + bool mayBenefitFromIndexForIn(const ASTPtr & node) const override; + +private: + size_t bits_per_row; + size_t hash_functions; +}; + +} diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp b/dbms/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp new file mode 100644 index 00000000000..9c8a9d4b41c --- /dev/null +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp @@ -0,0 +1,352 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +namespace +{ + +PreparedSetKey getPreparedSetKey(const ASTPtr & node, const DataTypePtr & data_type) +{ + /// If the data type is tuple, let's try unbox once + if (node->as() || node->as()) + return PreparedSetKey::forSubquery(*node); + + if (const auto * date_type_tuple = typeid_cast(&*data_type)) + return PreparedSetKey::forLiteral(*node, date_type_tuple->getElements()); + + return PreparedSetKey::forLiteral(*node, DataTypes(1, data_type)); +} + +ColumnWithTypeAndName getPreparedSetInfo(const SetPtr & prepared_set) +{ + if (prepared_set->getDataTypes().size() == 1) + return {prepared_set->getSetElements()[0], prepared_set->getDataTypes()[0], "dummy"}; + + return {ColumnTuple::create(prepared_set->getSetElements()), std::make_shared(prepared_set->getDataTypes()), "dummy"}; +} + +bool maybeTrueOnBloomFilter(const IColumn * hash_column, const BloomFilterPtr & bloom_filter, size_t hash_functions) +{ + const auto const_column = typeid_cast(hash_column); + const auto non_const_column = typeid_cast(hash_column); + + if (!const_column && !non_const_column) + throw Exception("LOGICAL ERROR: hash column must be Const Column or UInt64 Column.", ErrorCodes::LOGICAL_ERROR); + + if (const_column) + { + for (size_t index = 0; index < hash_functions; ++index) + if (!bloom_filter->findHashWithSeed(const_column->getValue(), BloomFilterHash::bf_hash_seed[index])) + return false; + return true; + } + else + { + bool missing_rows = true; + const ColumnUInt64::Container & data = non_const_column->getData(); + + for (size_t index = 0, size = data.size(); missing_rows && index < size; ++index) + { + bool match_row = true; + for (size_t hash_index = 0; match_row && hash_index < hash_functions; ++hash_index) + match_row = bloom_filter->findHashWithSeed(data[index], BloomFilterHash::bf_hash_seed[hash_index]); + + missing_rows = !match_row; + } + + return !missing_rows; + } +} + +} + +MergeTreeIndexConditionBloomFilter::MergeTreeIndexConditionBloomFilter( + const SelectQueryInfo & info, const Context & context, const Block & header, size_t hash_functions) + : header(header), context(context), query_info(info), hash_functions(hash_functions) +{ + auto atomFromAST = [this](auto & node, auto &, auto & constants, auto & out) { return traverseAtomAST(node, constants, out); }; + rpn = std::move(RPNBuilder(info, context, atomFromAST).extractRPN()); +} + +bool MergeTreeIndexConditionBloomFilter::alwaysUnknownOrTrue() const +{ + std::vector rpn_stack; + + for (const auto & element : rpn) + { + if (element.function == RPNElement::FUNCTION_UNKNOWN + || element.function == RPNElement::ALWAYS_TRUE) + { + rpn_stack.push_back(true); + } + else if (element.function == RPNElement::FUNCTION_EQUALS + || element.function == RPNElement::FUNCTION_NOT_EQUALS + || element.function == RPNElement::FUNCTION_IN + || element.function == RPNElement::FUNCTION_NOT_IN + || element.function == RPNElement::ALWAYS_FALSE) + { + rpn_stack.push_back(false); + } + else if (element.function == RPNElement::FUNCTION_NOT) + { + // do nothing + } + else if (element.function == RPNElement::FUNCTION_AND) + { + auto arg1 = rpn_stack.back(); + rpn_stack.pop_back(); + auto arg2 = rpn_stack.back(); + rpn_stack.back() = arg1 && arg2; + } + else if (element.function == RPNElement::FUNCTION_OR) + { + auto arg1 = rpn_stack.back(); + rpn_stack.pop_back(); + auto arg2 = rpn_stack.back(); + rpn_stack.back() = arg1 || arg2; + } + else + throw Exception("Unexpected function type in KeyCondition::RPNElement", ErrorCodes::LOGICAL_ERROR); + } + + return rpn_stack[0]; +} + +bool MergeTreeIndexConditionBloomFilter::mayBeTrueOnGranule(const MergeTreeIndexGranuleBloomFilter * granule) const +{ + std::vector rpn_stack; + const auto & filters = granule->getFilters(); + + for (const auto & element : rpn) + { + if (element.function == RPNElement::FUNCTION_UNKNOWN) + { + rpn_stack.emplace_back(true, true); + } + else if (element.function == RPNElement::FUNCTION_IN + || element.function == RPNElement::FUNCTION_NOT_IN + || element.function == RPNElement::FUNCTION_EQUALS + || element.function == RPNElement::FUNCTION_NOT_EQUALS) + { + bool match_rows = true; + const auto & predicate = element.predicate; + for (size_t index = 0; match_rows && index < predicate.size(); ++index) + { + const auto & query_index_hash = predicate[index]; + const auto & filter = filters[query_index_hash.first]; + const ColumnPtr & hash_column = query_index_hash.second; + match_rows = maybeTrueOnBloomFilter(&*hash_column, filter, hash_functions); + } + + rpn_stack.emplace_back(match_rows, !match_rows); + if (element.function == RPNElement::FUNCTION_NOT_EQUALS || element.function == RPNElement::FUNCTION_NOT_IN) + rpn_stack.back() = !rpn_stack.back(); + } + else if (element.function == RPNElement::FUNCTION_NOT) + { + rpn_stack.back() = !rpn_stack.back(); + } + else if (element.function == RPNElement::FUNCTION_OR) + { + auto arg1 = rpn_stack.back(); + rpn_stack.pop_back(); + auto arg2 = rpn_stack.back(); + rpn_stack.back() = arg1 | arg2; + } + else if (element.function == RPNElement::FUNCTION_AND) + { + auto arg1 = rpn_stack.back(); + rpn_stack.pop_back(); + auto arg2 = rpn_stack.back(); + rpn_stack.back() = arg1 & arg2; + } + else if (element.function == RPNElement::ALWAYS_TRUE) + { + rpn_stack.emplace_back(true, false); + } + else if (element.function == RPNElement::ALWAYS_FALSE) + { + rpn_stack.emplace_back(false, true); + } + else + throw Exception("Unexpected function type in KeyCondition::RPNElement", ErrorCodes::LOGICAL_ERROR); + } + + if (rpn_stack.size() != 1) + throw Exception("Unexpected stack size in KeyCondition::mayBeTrueInRange", ErrorCodes::LOGICAL_ERROR); + + return rpn_stack[0].can_be_true; +} + +bool MergeTreeIndexConditionBloomFilter::traverseAtomAST(const ASTPtr & node, Block & block_with_constants, RPNElement & out) +{ + { + Field const_value; + DataTypePtr const_type; + if (KeyCondition::getConstant(node, block_with_constants, const_value, const_type)) + { + if (const_value.getType() == Field::Types::UInt64 || const_value.getType() == Field::Types::Int64 || + const_value.getType() == Field::Types::Float64) + { + /// Zero in all types is represented in memory the same way as in UInt64. + out.function = const_value.get() ? RPNElement::ALWAYS_TRUE : RPNElement::ALWAYS_FALSE; + return true; + } + } + } + + if (const auto * function = node->as()) + { + const ASTs & arguments = function->arguments->children; + + if (arguments.size() != 2) + return false; + + if (functionIsInOrGlobalInOperator(function->name)) + { + if (const auto & prepared_set = getPreparedSet(arguments[1])) + return traverseASTIn(function->name, arguments[0], prepared_set, out); + } + else if (function->name == "equals" || function->name == "notEquals") + { + Field const_value; + DataTypePtr const_type; + if (KeyCondition::getConstant(arguments[1], block_with_constants, const_value, const_type)) + return traverseASTEquals(function->name, arguments[0], const_type, const_value, out); + else if (KeyCondition::getConstant(arguments[0], block_with_constants, const_value, const_type)) + return traverseASTEquals(function->name, arguments[1], const_type, const_value, out); + } + } + + return false; +} + +bool MergeTreeIndexConditionBloomFilter::traverseASTIn( + const String & function_name, const ASTPtr & key_ast, const SetPtr & prepared_set, RPNElement & out) +{ + const auto & prepared_info = getPreparedSetInfo(prepared_set); + return traverseASTIn(function_name, key_ast, prepared_info.type, prepared_info.column, out); +} + +bool MergeTreeIndexConditionBloomFilter::traverseASTIn( + const String & function_name, const ASTPtr & key_ast, const DataTypePtr & type, const ColumnPtr & column, RPNElement & out) +{ + if (header.has(key_ast->getColumnName())) + { + size_t row_size = column->size(); + size_t position = header.getPositionByName(key_ast->getColumnName()); + const DataTypePtr & index_type = header.getByPosition(position).type; + const auto & converted_column = castColumn(ColumnWithTypeAndName{column, type, ""}, index_type, context); + out.predicate.emplace_back(std::make_pair(position, BloomFilterHash::hashWithColumn(index_type, converted_column, 0, row_size))); + + if (function_name == "in" || function_name == "globalIn") + out.function = RPNElement::FUNCTION_IN; + + if (function_name == "notIn" || function_name == "globalNotIn") + out.function = RPNElement::FUNCTION_NOT_IN; + + return true; + } + + if (const auto * function = key_ast->as()) + { + WhichDataType which(type); + + if (which.isTuple() && function->name == "tuple") + { + const auto & tuple_column = typeid_cast(column.get()); + const auto & tuple_data_type = typeid_cast(type.get()); + const ASTs & arguments = typeid_cast(*function->arguments).children; + + if (tuple_data_type->getElements().size() != arguments.size() || tuple_column->getColumns().size() != arguments.size()) + throw Exception("Illegal types of arguments of function " + function_name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + + bool match_with_subtype = false; + const auto & sub_columns = tuple_column->getColumns(); + const auto & sub_data_types = tuple_data_type->getElements(); + + for (size_t index = 0; index < arguments.size(); ++index) + match_with_subtype |= traverseASTIn(function_name, arguments[index], sub_data_types[index], sub_columns[index], out); + + return match_with_subtype; + } + } + + return false; +} + +bool MergeTreeIndexConditionBloomFilter::traverseASTEquals( + const String & function_name, const ASTPtr & key_ast, const DataTypePtr & value_type, const Field & value_field, RPNElement & out) +{ + if (header.has(key_ast->getColumnName())) + { + size_t position = header.getPositionByName(key_ast->getColumnName()); + const DataTypePtr & index_type = header.getByPosition(position).type; + Field converted_field = convertFieldToType(value_field, *index_type, &*value_type); + out.predicate.emplace_back(std::make_pair(position, BloomFilterHash::hashWithField(&*index_type, converted_field))); + out.function = function_name == "equals" ? RPNElement::FUNCTION_EQUALS : RPNElement::FUNCTION_NOT_EQUALS; + return true; + } + + if (const auto * function = key_ast->as()) + { + WhichDataType which(value_type); + + if (which.isTuple() && function->name == "tuple") + { + const TupleBackend & tuple = get(value_field).toUnderType(); + const auto value_tuple_data_type = typeid_cast(value_type.get()); + const ASTs & arguments = typeid_cast(*function->arguments).children; + + if (tuple.size() != arguments.size()) + throw Exception("Illegal types of arguments of function " + function_name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + + bool match_with_subtype = false; + const DataTypes & subtypes = value_tuple_data_type->getElements(); + + for (size_t index = 0; index < tuple.size(); ++index) + match_with_subtype |= traverseASTEquals(function_name, arguments[index], subtypes[index], tuple[index], out); + + return match_with_subtype; + } + } + + return false; +} + +SetPtr MergeTreeIndexConditionBloomFilter::getPreparedSet(const ASTPtr & node) +{ + if (header.has(node->getColumnName())) + { + const auto & column_and_type = header.getByName(node->getColumnName()); + const auto & prepared_set_it = query_info.sets.find(getPreparedSetKey(node, column_and_type.type)); + + if (prepared_set_it != query_info.sets.end() && prepared_set_it->second->hasExplicitSetElements()) + return prepared_set_it->second; + } + else + { + for (const auto & prepared_set_it : query_info.sets) + if (prepared_set_it.first.ast_hash == node->getTreeHash() && prepared_set_it.second->hasExplicitSetElements()) + return prepared_set_it.second; + } + + return DB::SetPtr(); +} + +} diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.h b/dbms/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.h new file mode 100644 index 00000000000..6c268cadbb6 --- /dev/null +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace DB +{ + +class MergeTreeIndexConditionBloomFilter : public IMergeTreeIndexCondition +{ +public: + struct RPNElement + { + enum Function + { + /// Atoms of a Boolean expression. + FUNCTION_EQUALS, + FUNCTION_NOT_EQUALS, + FUNCTION_IN, + FUNCTION_NOT_IN, + FUNCTION_UNKNOWN, /// Can take any value. + /// Operators of the logical expression. + FUNCTION_NOT, + FUNCTION_AND, + FUNCTION_OR, + /// Constants + ALWAYS_FALSE, + ALWAYS_TRUE, + }; + + RPNElement(Function function_ = FUNCTION_UNKNOWN) : function(function_) {} + + Function function = FUNCTION_UNKNOWN; + std::vector> predicate; + }; + + MergeTreeIndexConditionBloomFilter(const SelectQueryInfo & info, const Context & context, const Block & header, size_t hash_functions); + + bool alwaysUnknownOrTrue() const override; + + bool mayBeTrueOnGranule(MergeTreeIndexGranulePtr granule) const override + { + if (const auto & bf_granule = typeid_cast(granule.get())) + return mayBeTrueOnGranule(bf_granule); + + throw Exception("LOGICAL ERROR: require bloom filter index granule.", ErrorCodes::LOGICAL_ERROR); + } + +private: + const Block & header; + const Context & context; + const SelectQueryInfo & query_info; + const size_t hash_functions; + std::vector rpn; + + SetPtr getPreparedSet(const ASTPtr & node); + + bool mayBeTrueOnGranule(const MergeTreeIndexGranuleBloomFilter * granule) const; + + bool traverseAtomAST(const ASTPtr & node, Block & block_with_constants, RPNElement & out); + + bool traverseASTIn(const String & function_name, const ASTPtr & key_ast, const SetPtr & prepared_set, RPNElement & out); + + bool traverseASTIn( + const String & function_name, const ASTPtr & key_ast, const DataTypePtr & type, const ColumnPtr & column, RPNElement & out); + + bool traverseASTEquals( + const String & function_name, const ASTPtr & key_ast, const DataTypePtr & value_type, const Field & value_field, RPNElement & out); +}; + +} diff --git a/dbms/src/Storages/MergeTree/MergeTreeBloomFilterIndex.cpp b/dbms/src/Storages/MergeTree/MergeTreeIndexFullText.cpp similarity index 87% rename from dbms/src/Storages/MergeTree/MergeTreeBloomFilterIndex.cpp rename to dbms/src/Storages/MergeTree/MergeTreeIndexFullText.cpp index 9c51428f0a2..895764339e5 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeBloomFilterIndex.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexFullText.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -31,7 +31,7 @@ namespace ErrorCodes /// Adds all tokens from string to bloom filter. static void stringToBloomFilter( - const char * data, size_t size, const std::unique_ptr & token_extractor, StringBloomFilter & bloom_filter) + const char * data, size_t size, const std::unique_ptr & token_extractor, BloomFilter & bloom_filter) { size_t cur = 0; size_t token_start = 0; @@ -42,7 +42,7 @@ static void stringToBloomFilter( /// Adds all tokens from like pattern string to bloom filter. (Because like pattern can contain `\%` and `\_`.) static void likeStringToBloomFilter( - const String & data, const std::unique_ptr & token_extractor, StringBloomFilter & bloom_filter) + const String & data, const std::unique_ptr & token_extractor, BloomFilter & bloom_filter) { size_t cur = 0; String token; @@ -51,24 +51,23 @@ static void likeStringToBloomFilter( } -MergeTreeBloomFilterIndexGranule::MergeTreeBloomFilterIndexGranule(const MergeTreeBloomFilterIndex & index) +MergeTreeIndexGranuleFullText::MergeTreeIndexGranuleFullText(const MergeTreeIndexFullText & index) : IMergeTreeIndexGranule() , index(index) , bloom_filters( - index.columns.size(), StringBloomFilter(index.bloom_filter_size, index.bloom_filter_hashes, index.seed)) + index.columns.size(), BloomFilter(index.bloom_filter_size, index.bloom_filter_hashes, index.seed)) , has_elems(false) {} -void MergeTreeBloomFilterIndexGranule::serializeBinary(WriteBuffer & ostr) const +void MergeTreeIndexGranuleFullText::serializeBinary(WriteBuffer & ostr) const { if (empty()) - throw Exception( - "Attempt to write empty minmax index " + backQuote(index.name), ErrorCodes::LOGICAL_ERROR); + throw Exception("Attempt to write empty minmax index " + backQuote(index.name), ErrorCodes::LOGICAL_ERROR); for (const auto & bloom_filter : bloom_filters) ostr.write(reinterpret_cast(bloom_filter.getFilter().data()), index.bloom_filter_size); } -void MergeTreeBloomFilterIndexGranule::deserializeBinary(ReadBuffer & istr) +void MergeTreeIndexGranuleFullText::deserializeBinary(ReadBuffer & istr) { for (auto & bloom_filter : bloom_filters) { @@ -78,17 +77,17 @@ void MergeTreeBloomFilterIndexGranule::deserializeBinary(ReadBuffer & istr) } -MergeTreeBloomFilterIndexAggregator::MergeTreeBloomFilterIndexAggregator(const MergeTreeBloomFilterIndex & index) - : index(index), granule(std::make_shared(index)) {} +MergeTreeIndexAggregatorFullText::MergeTreeIndexAggregatorFullText(const MergeTreeIndexFullText & index) + : index(index), granule(std::make_shared(index)) {} -MergeTreeIndexGranulePtr MergeTreeBloomFilterIndexAggregator::getGranuleAndReset() +MergeTreeIndexGranulePtr MergeTreeIndexAggregatorFullText::getGranuleAndReset() { - auto new_granule = std::make_shared(index); + auto new_granule = std::make_shared(index); new_granule.swap(granule); return new_granule; } -void MergeTreeBloomFilterIndexAggregator::update(const Block & block, size_t * pos, size_t limit) +void MergeTreeIndexAggregatorFullText::update(const Block & block, size_t * pos, size_t limit) { if (*pos >= block.rows()) throw Exception( @@ -111,14 +110,14 @@ void MergeTreeBloomFilterIndexAggregator::update(const Block & block, size_t * p } -const BloomFilterCondition::AtomMap BloomFilterCondition::atom_map +const MergeTreeConditionFullText::AtomMap MergeTreeConditionFullText::atom_map { { "notEquals", - [] (RPNElement & out, const Field & value, const MergeTreeBloomFilterIndex & idx) + [] (RPNElement & out, const Field & value, const MergeTreeIndexFullText & idx) { out.function = RPNElement::FUNCTION_NOT_EQUALS; - out.bloom_filter = std::make_unique( + out.bloom_filter = std::make_unique( idx.bloom_filter_size, idx.bloom_filter_hashes, idx.seed); const auto & str = value.get(); @@ -128,10 +127,10 @@ const BloomFilterCondition::AtomMap BloomFilterCondition::atom_map }, { "equals", - [] (RPNElement & out, const Field & value, const MergeTreeBloomFilterIndex & idx) + [] (RPNElement & out, const Field & value, const MergeTreeIndexFullText & idx) { out.function = RPNElement::FUNCTION_EQUALS; - out.bloom_filter = std::make_unique( + out.bloom_filter = std::make_unique( idx.bloom_filter_size, idx.bloom_filter_hashes, idx.seed); const auto & str = value.get(); @@ -141,10 +140,10 @@ const BloomFilterCondition::AtomMap BloomFilterCondition::atom_map }, { "like", - [] (RPNElement & out, const Field & value, const MergeTreeBloomFilterIndex & idx) + [] (RPNElement & out, const Field & value, const MergeTreeIndexFullText & idx) { out.function = RPNElement::FUNCTION_LIKE; - out.bloom_filter = std::make_unique( + out.bloom_filter = std::make_unique( idx.bloom_filter_size, idx.bloom_filter_hashes, idx.seed); const auto & str = value.get(); @@ -154,7 +153,7 @@ const BloomFilterCondition::AtomMap BloomFilterCondition::atom_map }, { "notIn", - [] (RPNElement & out, const Field &, const MergeTreeBloomFilterIndex &) + [] (RPNElement & out, const Field &, const MergeTreeIndexFullText &) { out.function = RPNElement::FUNCTION_NOT_IN; return true; @@ -162,7 +161,7 @@ const BloomFilterCondition::AtomMap BloomFilterCondition::atom_map }, { "in", - [] (RPNElement & out, const Field &, const MergeTreeBloomFilterIndex &) + [] (RPNElement & out, const Field &, const MergeTreeIndexFullText &) { out.function = RPNElement::FUNCTION_IN; return true; @@ -170,24 +169,21 @@ const BloomFilterCondition::AtomMap BloomFilterCondition::atom_map }, }; -BloomFilterCondition::BloomFilterCondition( +MergeTreeConditionFullText::MergeTreeConditionFullText( const SelectQueryInfo & query_info, const Context & context, - const MergeTreeBloomFilterIndex & index_) : index(index_), prepared_sets(query_info.sets) + const MergeTreeIndexFullText & index_) : index(index_), prepared_sets(query_info.sets) { rpn = std::move( RPNBuilder( query_info, context, - [this] (const ASTPtr & node, - const Context & /* context */, - Block & block_with_constants, - RPNElement & out) -> bool + [this] (const ASTPtr & node, const Context & /* context */, Block & block_with_constants, RPNElement & out) -> bool { return this->atomFromAST(node, block_with_constants, out); }).extractRPN()); } -bool BloomFilterCondition::alwaysUnknownOrTrue() const +bool MergeTreeConditionFullText::alwaysUnknownOrTrue() const { /// Check like in KeyCondition. std::vector rpn_stack; @@ -234,10 +230,10 @@ bool BloomFilterCondition::alwaysUnknownOrTrue() const return rpn_stack[0]; } -bool BloomFilterCondition::mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granule) const +bool MergeTreeConditionFullText::mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granule) const { - std::shared_ptr granule - = std::dynamic_pointer_cast(idx_granule); + std::shared_ptr granule + = std::dynamic_pointer_cast(idx_granule); if (!granule) throw Exception( "BloomFilter index condition got a granule with the wrong type.", ErrorCodes::LOGICAL_ERROR); @@ -323,7 +319,7 @@ bool BloomFilterCondition::mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granu return rpn_stack[0].can_be_true; } -bool BloomFilterCondition::getKey(const ASTPtr & node, size_t & key_column_num) +bool MergeTreeConditionFullText::getKey(const ASTPtr & node, size_t & key_column_num) { auto it = std::find(index.columns.begin(), index.columns.end(), node->getColumnName()); if (it == index.columns.end()) @@ -333,7 +329,7 @@ bool BloomFilterCondition::getKey(const ASTPtr & node, size_t & key_column_num) return true; } -bool BloomFilterCondition::atomFromAST( +bool MergeTreeConditionFullText::atomFromAST( const ASTPtr & node, Block & block_with_constants, RPNElement & out) { Field const_value; @@ -399,7 +395,7 @@ bool BloomFilterCondition::atomFromAST( return false; } -bool BloomFilterCondition::tryPrepareSetBloomFilter( +bool MergeTreeConditionFullText::tryPrepareSetBloomFilter( const ASTs & args, RPNElement & out) { @@ -454,7 +450,7 @@ bool BloomFilterCondition::tryPrepareSetBloomFilter( if (data_type->getTypeId() != TypeIndex::String && data_type->getTypeId() != TypeIndex::FixedString) return false; - std::vector> bloom_filters; + std::vector> bloom_filters; std::vector key_position; Columns columns = prepared_set->getSetElements(); @@ -480,23 +476,23 @@ bool BloomFilterCondition::tryPrepareSetBloomFilter( } -MergeTreeIndexGranulePtr MergeTreeBloomFilterIndex::createIndexGranule() const +MergeTreeIndexGranulePtr MergeTreeIndexFullText::createIndexGranule() const { - return std::make_shared(*this); + return std::make_shared(*this); } -MergeTreeIndexAggregatorPtr MergeTreeBloomFilterIndex::createIndexAggregator() const +MergeTreeIndexAggregatorPtr MergeTreeIndexFullText::createIndexAggregator() const { - return std::make_shared(*this); + return std::make_shared(*this); } -IndexConditionPtr MergeTreeBloomFilterIndex::createIndexCondition( +MergeTreeIndexConditionPtr MergeTreeIndexFullText::createIndexCondition( const SelectQueryInfo & query, const Context & context) const { - return std::make_shared(query, context, *this); + return std::make_shared(query, context, *this); }; -bool MergeTreeBloomFilterIndex::mayBenefitFromIndexForIn(const ASTPtr & node) const +bool MergeTreeIndexFullText::mayBenefitFromIndexForIn(const ASTPtr & node) const { return std::find(std::cbegin(columns), std::cend(columns), node->getColumnName()) != std::cend(columns); } @@ -679,7 +675,7 @@ std::unique_ptr bloomFilterIndexCreator( auto tokenizer = std::make_unique(n); - return std::make_unique( + return std::make_unique( node->name, std::move(index_expr), columns, data_types, sample, node->granularity, bloom_filter_size, bloom_filter_hashes, seed, std::move(tokenizer)); } @@ -697,7 +693,7 @@ std::unique_ptr bloomFilterIndexCreator( auto tokenizer = std::make_unique(); - return std::make_unique( + return std::make_unique( node->name, std::move(index_expr), columns, data_types, sample, node->granularity, bloom_filter_size, bloom_filter_hashes, seed, std::move(tokenizer)); } diff --git a/dbms/src/Storages/MergeTree/MergeTreeBloomFilterIndex.h b/dbms/src/Storages/MergeTree/MergeTreeIndexFullText.h similarity index 79% rename from dbms/src/Storages/MergeTree/MergeTreeBloomFilterIndex.h rename to dbms/src/Storages/MergeTree/MergeTreeIndexFullText.h index 888ffe7f9cc..cd8ac534e64 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeBloomFilterIndex.h +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexFullText.h @@ -10,54 +10,54 @@ namespace DB { -class MergeTreeBloomFilterIndex; +class MergeTreeIndexFullText; -struct MergeTreeBloomFilterIndexGranule : public IMergeTreeIndexGranule +struct MergeTreeIndexGranuleFullText : public IMergeTreeIndexGranule { - explicit MergeTreeBloomFilterIndexGranule( - const MergeTreeBloomFilterIndex & index); + explicit MergeTreeIndexGranuleFullText( + const MergeTreeIndexFullText & index); - ~MergeTreeBloomFilterIndexGranule() override = default; + ~MergeTreeIndexGranuleFullText() override = default; void serializeBinary(WriteBuffer & ostr) const override; void deserializeBinary(ReadBuffer & istr) override; bool empty() const override { return !has_elems; } - const MergeTreeBloomFilterIndex & index; - std::vector bloom_filters; + const MergeTreeIndexFullText & index; + std::vector bloom_filters; bool has_elems; }; -using MergeTreeBloomFilterIndexGranulePtr = std::shared_ptr; +using MergeTreeIndexGranuleFullTextPtr = std::shared_ptr; -struct MergeTreeBloomFilterIndexAggregator : IMergeTreeIndexAggregator +struct MergeTreeIndexAggregatorFullText : IMergeTreeIndexAggregator { - explicit MergeTreeBloomFilterIndexAggregator(const MergeTreeBloomFilterIndex & index); + explicit MergeTreeIndexAggregatorFullText(const MergeTreeIndexFullText & index); - ~MergeTreeBloomFilterIndexAggregator() override = default; + ~MergeTreeIndexAggregatorFullText() override = default; bool empty() const override { return !granule || granule->empty(); } MergeTreeIndexGranulePtr getGranuleAndReset() override; void update(const Block & block, size_t * pos, size_t limit) override; - const MergeTreeBloomFilterIndex & index; - MergeTreeBloomFilterIndexGranulePtr granule; + const MergeTreeIndexFullText & index; + MergeTreeIndexGranuleFullTextPtr granule; }; -class BloomFilterCondition : public IIndexCondition +class MergeTreeConditionFullText : public IMergeTreeIndexCondition { public: - BloomFilterCondition( + MergeTreeConditionFullText( const SelectQueryInfo & query_info, const Context & context, - const MergeTreeBloomFilterIndex & index_); + const MergeTreeIndexFullText & index_); - ~BloomFilterCondition() override = default; + ~MergeTreeConditionFullText() override = default; bool alwaysUnknownOrTrue() const override; @@ -93,19 +93,19 @@ private: }; RPNElement( - Function function_ = FUNCTION_UNKNOWN, size_t key_column_ = 0, std::unique_ptr && const_bloom_filter_ = nullptr) + Function function_ = FUNCTION_UNKNOWN, size_t key_column_ = 0, std::unique_ptr && const_bloom_filter_ = nullptr) : function(function_), key_column(key_column_), bloom_filter(std::move(const_bloom_filter_)) {} Function function = FUNCTION_UNKNOWN; /// For FUNCTION_EQUALS, FUNCTION_NOT_EQUALS, FUNCTION_LIKE, FUNCTION_NOT_LIKE. size_t key_column; - std::unique_ptr bloom_filter; + std::unique_ptr bloom_filter; /// For FUNCTION_IN and FUNCTION_NOT_IN - std::vector> set_bloom_filters; + std::vector> set_bloom_filters; std::vector set_key_position; }; - using AtomMap = std::unordered_map; + using AtomMap = std::unordered_map; using RPN = std::vector; bool atomFromAST(const ASTPtr & node, Block & block_with_constants, RPNElement & out); @@ -115,7 +115,7 @@ private: static const AtomMap atom_map; - const MergeTreeBloomFilterIndex & index; + const MergeTreeIndexFullText & index; RPN rpn; /// Sets from syntax analyzer. PreparedSets prepared_sets; @@ -164,10 +164,10 @@ struct SplitTokenExtractor : public ITokenExtractor }; -class MergeTreeBloomFilterIndex : public IMergeTreeIndex +class MergeTreeIndexFullText : public IMergeTreeIndex { public: - MergeTreeBloomFilterIndex( + MergeTreeIndexFullText( String name_, ExpressionActionsPtr expr_, const Names & columns_, @@ -184,12 +184,12 @@ public: , seed(seed_) , token_extractor_func(std::move(token_extractor_func_)) {} - ~MergeTreeBloomFilterIndex() override = default; + ~MergeTreeIndexFullText() override = default; MergeTreeIndexGranulePtr createIndexGranule() const override; MergeTreeIndexAggregatorPtr createIndexAggregator() const override; - IndexConditionPtr createIndexCondition( + MergeTreeIndexConditionPtr createIndexCondition( const SelectQueryInfo & query, const Context & context) const override; bool mayBenefitFromIndexForIn(const ASTPtr & node) const override; diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexGranularity.h b/dbms/src/Storages/MergeTree/MergeTreeIndexGranularity.h index 89651f75838..ff391be596c 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeIndexGranularity.h +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexGranularity.h @@ -62,6 +62,14 @@ public: return getMarkRows(last); } + size_t getLastNonFinalMarkRows() const + { + size_t last_mark_rows = getLastMarkRows(); + if (last_mark_rows != 0) + return last_mark_rows; + return getMarkRows(marks_rows_partial_sums.size() - 2); + } + bool hasFinalMark() const { return getLastMarkRows() == 0; diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexGranularityInfo.cpp b/dbms/src/Storages/MergeTree/MergeTreeIndexGranularityInfo.cpp new file mode 100644 index 00000000000..63b19da9e64 --- /dev/null +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexGranularityInfo.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include + +namespace DB +{ +std::optional MergeTreeIndexGranularityInfo::getMrkExtensionFromFS(const std::string & path_to_part) const +{ + if (Poco::File(path_to_part).exists()) + { + Poco::DirectoryIterator end; + for (Poco::DirectoryIterator part_it(path_to_part); part_it != end; ++part_it) + { + const auto & ext = "." + part_it.path().getExtension(); + if (ext == getNonAdaptiveMrkExtension() || ext == getAdaptiveMrkExtension()) + return ext; + } + } + return {}; +} + +MergeTreeIndexGranularityInfo::MergeTreeIndexGranularityInfo( + const MergeTreeData & storage) +{ + fixed_index_granularity = storage.settings.index_granularity; + /// Granularity is fixed + if (!storage.canUseAdaptiveGranularity()) + setNonAdaptive(); + else + setAdaptive(storage.settings.index_granularity_bytes); +} + + +void MergeTreeIndexGranularityInfo::changeGranularityIfRequired(const std::string & path_to_part) +{ + auto mrk_ext = getMrkExtensionFromFS(path_to_part); + if (mrk_ext && *mrk_ext == getNonAdaptiveMrkExtension()) + setNonAdaptive(); +} + +void MergeTreeIndexGranularityInfo::setAdaptive(size_t index_granularity_bytes_) +{ + is_adaptive = true; + mark_size_in_bytes = getAdaptiveMrkSize(); + marks_file_extension = getAdaptiveMrkExtension(); + index_granularity_bytes = index_granularity_bytes_; +} + +void MergeTreeIndexGranularityInfo::setNonAdaptive() +{ + is_adaptive = false; + mark_size_in_bytes = getNonAdaptiveMrkSize(); + marks_file_extension = getNonAdaptiveMrkExtension(); + index_granularity_bytes = 0; +} + +} diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexGranularityInfo.h b/dbms/src/Storages/MergeTree/MergeTreeIndexGranularityInfo.h new file mode 100644 index 00000000000..0c203aca8ab --- /dev/null +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexGranularityInfo.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include + +namespace DB +{ + +class MergeTreeData; +/// Meta information about index granularity +struct MergeTreeIndexGranularityInfo +{ +public: + /// Marks file extension '.mrk' or '.mrk2' + String marks_file_extension; + + /// Size of one mark in file two or three size_t numbers + UInt8 mark_size_in_bytes; + + /// Is stride in rows between marks non fixed? + bool is_adaptive; + + /// Fixed size in rows of one granule if index_granularity_bytes is zero + size_t fixed_index_granularity; + + /// Approximate bytes size of one granule + size_t index_granularity_bytes; + + MergeTreeIndexGranularityInfo( + const MergeTreeData & storage); + + void changeGranularityIfRequired(const std::string & path_to_part); + + String getMarksFilePath(const String & column_path) const + { + return column_path + marks_file_extension; + } +private: + + void setAdaptive(size_t index_granularity_bytes_); + void setNonAdaptive(); + std::optional getMrkExtensionFromFS(const std::string & path_to_table) const; +}; + +constexpr inline auto getNonAdaptiveMrkExtension() { return ".mrk"; } +constexpr inline auto getAdaptiveMrkExtension() { return ".mrk2"; } +constexpr inline auto getNonAdaptiveMrkSize() { return sizeof(UInt64) * 2; } +constexpr inline auto getAdaptiveMrkSize() { return sizeof(UInt64) * 3; } + +} diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexGranularityInfo.h.gch b/dbms/src/Storages/MergeTree/MergeTreeIndexGranularityInfo.h.gch new file mode 100644 index 00000000000..1bc281d90b3 Binary files /dev/null and b/dbms/src/Storages/MergeTree/MergeTreeIndexGranularityInfo.h.gch differ diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexGranuleBloomFilter.cpp b/dbms/src/Storages/MergeTree/MergeTreeIndexGranuleBloomFilter.cpp new file mode 100644 index 00000000000..4eee7309811 --- /dev/null +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexGranuleBloomFilter.cpp @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace DB +{ + +MergeTreeIndexGranuleBloomFilter::MergeTreeIndexGranuleBloomFilter(size_t bits_per_row, size_t hash_functions, size_t index_columns) + : bits_per_row(bits_per_row), hash_functions(hash_functions) +{ + total_rows = 0; + bloom_filters.resize(index_columns); +} + +MergeTreeIndexGranuleBloomFilter::MergeTreeIndexGranuleBloomFilter( + size_t bits_per_row, size_t hash_functions, size_t total_rows, const Blocks & granule_index_blocks) + : total_rows(total_rows), bits_per_row(bits_per_row), hash_functions(hash_functions) +{ + if (granule_index_blocks.empty() || !total_rows) + throw Exception("LOGICAL ERROR: granule_index_blocks empty or total_rows is zero.", ErrorCodes::LOGICAL_ERROR); + + assertGranuleBlocksStructure(granule_index_blocks); + + for (size_t index = 0; index < granule_index_blocks.size(); ++index) + { + Block granule_index_block = granule_index_blocks[index]; + + if (unlikely(!granule_index_block || !granule_index_block.rows())) + throw Exception("LOGICAL ERROR: granule_index_block is empty.", ErrorCodes::LOGICAL_ERROR); + + if (index == 0) + { + static size_t atom_size = 8; + size_t bytes_size = (bits_per_row * total_rows + atom_size - 1) / atom_size; + + for (size_t column = 0, columns = granule_index_block.columns(); column < columns; ++column) + bloom_filters.emplace_back(std::make_shared(bytes_size, hash_functions, 0)); + } + + for (size_t column = 0, columns = granule_index_block.columns(); column < columns; ++column) + fillingBloomFilter(bloom_filters[column], granule_index_block, column); + } +} + +bool MergeTreeIndexGranuleBloomFilter::empty() const +{ + return !total_rows; +} + +void MergeTreeIndexGranuleBloomFilter::deserializeBinary(ReadBuffer & istr) +{ + if (!empty()) + throw Exception("Cannot read data to a non-empty bloom filter index.", ErrorCodes::LOGICAL_ERROR); + + readVarUInt(total_rows, istr); + for (size_t index = 0; index < bloom_filters.size(); ++index) + { + static size_t atom_size = 8; + size_t bytes_size = (bits_per_row * total_rows + atom_size - 1) / atom_size; + bloom_filters[index] = std::make_shared(bytes_size, hash_functions, 0); + istr.read(reinterpret_cast(bloom_filters[index]->getFilter().data()), bytes_size); + } +} + +void MergeTreeIndexGranuleBloomFilter::serializeBinary(WriteBuffer & ostr) const +{ + if (empty()) + throw Exception("Attempt to write empty bloom filter index.", ErrorCodes::LOGICAL_ERROR); + + static size_t atom_size = 8; + writeVarUInt(total_rows, ostr); + size_t bytes_size = (bits_per_row * total_rows + atom_size - 1) / atom_size; + for (const auto & bloom_filter : bloom_filters) + ostr.write(reinterpret_cast(bloom_filter->getFilter().data()), bytes_size); +} + +void MergeTreeIndexGranuleBloomFilter::assertGranuleBlocksStructure(const Blocks & granule_index_blocks) const +{ + Block prev_block; + for (size_t index = 0; index < granule_index_blocks.size(); ++index) + { + Block granule_index_block = granule_index_blocks[index]; + + if (index != 0) + assertBlocksHaveEqualStructure(prev_block, granule_index_block, "Granule blocks of bloom filter has difference structure."); + + prev_block = granule_index_block; + } +} + +void MergeTreeIndexGranuleBloomFilter::fillingBloomFilter(BloomFilterPtr & bf, const Block & granule_index_block, size_t index_hash_column) +{ + const auto & column = granule_index_block.getByPosition(index_hash_column); + + if (const auto hash_column = typeid_cast(column.column.get())) + { + const auto & hash_column_vec = hash_column->getData(); + + for (size_t index = 0, size = hash_column_vec.size(); index < size; ++index) + { + const UInt64 & bf_base_hash = hash_column_vec[index]; + + for (size_t i = 0; i < hash_functions; ++i) + bf->addHashWithSeed(bf_base_hash, BloomFilterHash::bf_hash_seed[i]); + } + } +} + +} diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexGranuleBloomFilter.h b/dbms/src/Storages/MergeTree/MergeTreeIndexGranuleBloomFilter.h new file mode 100644 index 00000000000..79670678e79 --- /dev/null +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexGranuleBloomFilter.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +namespace DB +{ + +class MergeTreeIndexGranuleBloomFilter : public IMergeTreeIndexGranule +{ +public: + MergeTreeIndexGranuleBloomFilter(size_t bits_per_row, size_t hash_functions, size_t index_columns); + + MergeTreeIndexGranuleBloomFilter(size_t bits_per_row, size_t hash_functions, size_t total_rows, const Blocks & granule_index_blocks); + + bool empty() const override; + + void serializeBinary(WriteBuffer & ostr) const override; + + void deserializeBinary(ReadBuffer & istr) override; + + const std::vector getFilters() const { return bloom_filters; } + +private: + size_t total_rows; + size_t bits_per_row; + size_t hash_functions; + std::vector bloom_filters; + + void assertGranuleBlocksStructure(const Blocks & granule_index_blocks) const; + + void fillingBloomFilter(BloomFilterPtr & bf, const Block & granule_index_block, size_t index_hash_column); +}; + + +} diff --git a/dbms/src/Storages/MergeTree/MergeTreeMinMaxIndex.cpp b/dbms/src/Storages/MergeTree/MergeTreeIndexMinMax.cpp similarity index 74% rename from dbms/src/Storages/MergeTree/MergeTreeMinMaxIndex.cpp rename to dbms/src/Storages/MergeTree/MergeTreeIndexMinMax.cpp index 32baa186269..0d9c4722a25 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeMinMaxIndex.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexMinMax.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -16,14 +16,14 @@ namespace ErrorCodes } -MergeTreeMinMaxGranule::MergeTreeMinMaxGranule(const MergeTreeMinMaxIndex & index) +MergeTreeIndexGranuleMinMax::MergeTreeIndexGranuleMinMax(const MergeTreeIndexMinMax & index) : IMergeTreeIndexGranule(), index(index), parallelogram() {} -MergeTreeMinMaxGranule::MergeTreeMinMaxGranule( - const MergeTreeMinMaxIndex & index, std::vector && parallelogram) +MergeTreeIndexGranuleMinMax::MergeTreeIndexGranuleMinMax( + const MergeTreeIndexMinMax & index, std::vector && parallelogram) : IMergeTreeIndexGranule(), index(index), parallelogram(std::move(parallelogram)) {} -void MergeTreeMinMaxGranule::serializeBinary(WriteBuffer & ostr) const +void MergeTreeIndexGranuleMinMax::serializeBinary(WriteBuffer & ostr) const { if (empty()) throw Exception( @@ -50,7 +50,7 @@ void MergeTreeMinMaxGranule::serializeBinary(WriteBuffer & ostr) const } } -void MergeTreeMinMaxGranule::deserializeBinary(ReadBuffer & istr) +void MergeTreeIndexGranuleMinMax::deserializeBinary(ReadBuffer & istr) { parallelogram.clear(); Field min_val; @@ -83,15 +83,15 @@ void MergeTreeMinMaxGranule::deserializeBinary(ReadBuffer & istr) } -MergeTreeMinMaxAggregator::MergeTreeMinMaxAggregator(const MergeTreeMinMaxIndex & index) +MergeTreeIndexAggregatorMinMax::MergeTreeIndexAggregatorMinMax(const MergeTreeIndexMinMax & index) : index(index) {} -MergeTreeIndexGranulePtr MergeTreeMinMaxAggregator::getGranuleAndReset() +MergeTreeIndexGranulePtr MergeTreeIndexAggregatorMinMax::getGranuleAndReset() { - return std::make_shared(index, std::move(parallelogram)); + return std::make_shared(index, std::move(parallelogram)); } -void MergeTreeMinMaxAggregator::update(const Block & block, size_t * pos, size_t limit) +void MergeTreeIndexAggregatorMinMax::update(const Block & block, size_t * pos, size_t limit) { if (*pos >= block.rows()) throw Exception( @@ -122,21 +122,21 @@ void MergeTreeMinMaxAggregator::update(const Block & block, size_t * pos, size_t } -MinMaxCondition::MinMaxCondition( +MergeTreeIndexConditionMinMax::MergeTreeIndexConditionMinMax( const SelectQueryInfo &query, const Context &context, - const MergeTreeMinMaxIndex &index) - : IIndexCondition(), index(index), condition(query, context, index.columns, index.expr) {} + const MergeTreeIndexMinMax &index) + : IMergeTreeIndexCondition(), index(index), condition(query, context, index.columns, index.expr) {} -bool MinMaxCondition::alwaysUnknownOrTrue() const +bool MergeTreeIndexConditionMinMax::alwaysUnknownOrTrue() const { return condition.alwaysUnknownOrTrue(); } -bool MinMaxCondition::mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granule) const +bool MergeTreeIndexConditionMinMax::mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granule) const { - std::shared_ptr granule - = std::dynamic_pointer_cast(idx_granule); + std::shared_ptr granule + = std::dynamic_pointer_cast(idx_granule); if (!granule) throw Exception( "Minmax index condition got a granule with the wrong type.", ErrorCodes::LOGICAL_ERROR); @@ -147,25 +147,25 @@ bool MinMaxCondition::mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granule) c } -MergeTreeIndexGranulePtr MergeTreeMinMaxIndex::createIndexGranule() const +MergeTreeIndexGranulePtr MergeTreeIndexMinMax::createIndexGranule() const { - return std::make_shared(*this); + return std::make_shared(*this); } -MergeTreeIndexAggregatorPtr MergeTreeMinMaxIndex::createIndexAggregator() const +MergeTreeIndexAggregatorPtr MergeTreeIndexMinMax::createIndexAggregator() const { - return std::make_shared(*this); + return std::make_shared(*this); } -IndexConditionPtr MergeTreeMinMaxIndex::createIndexCondition( +MergeTreeIndexConditionPtr MergeTreeIndexMinMax::createIndexCondition( const SelectQueryInfo & query, const Context & context) const { - return std::make_shared(query, context, *this); + return std::make_shared(query, context, *this); }; -bool MergeTreeMinMaxIndex::mayBenefitFromIndexForIn(const ASTPtr & node) const +bool MergeTreeIndexMinMax::mayBenefitFromIndexForIn(const ASTPtr & node) const { const String column_name = node->getColumnName(); @@ -210,7 +210,7 @@ std::unique_ptr minmaxIndexCreator( data_types.emplace_back(column.type); } - return std::make_unique( + return std::make_unique( node->name, std::move(minmax_expr), columns, data_types, sample, node->granularity); } diff --git a/dbms/src/Storages/MergeTree/MergeTreeMinMaxIndex.h b/dbms/src/Storages/MergeTree/MergeTreeIndexMinMax.h similarity index 59% rename from dbms/src/Storages/MergeTree/MergeTreeMinMaxIndex.h rename to dbms/src/Storages/MergeTree/MergeTreeIndexMinMax.h index 06be8fe0cdd..5b514cdc738 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeMinMaxIndex.h +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexMinMax.h @@ -10,62 +10,62 @@ namespace DB { -class MergeTreeMinMaxIndex; +class MergeTreeIndexMinMax; -struct MergeTreeMinMaxGranule : public IMergeTreeIndexGranule +struct MergeTreeIndexGranuleMinMax : public IMergeTreeIndexGranule { - explicit MergeTreeMinMaxGranule(const MergeTreeMinMaxIndex & index); - MergeTreeMinMaxGranule(const MergeTreeMinMaxIndex & index, std::vector && parallelogram); - ~MergeTreeMinMaxGranule() override = default; + explicit MergeTreeIndexGranuleMinMax(const MergeTreeIndexMinMax & index); + MergeTreeIndexGranuleMinMax(const MergeTreeIndexMinMax & index, std::vector && parallelogram); + ~MergeTreeIndexGranuleMinMax() override = default; void serializeBinary(WriteBuffer & ostr) const override; void deserializeBinary(ReadBuffer & istr) override; bool empty() const override { return parallelogram.empty(); } - const MergeTreeMinMaxIndex & index; + const MergeTreeIndexMinMax & index; std::vector parallelogram; }; -struct MergeTreeMinMaxAggregator : IMergeTreeIndexAggregator +struct MergeTreeIndexAggregatorMinMax : IMergeTreeIndexAggregator { - explicit MergeTreeMinMaxAggregator(const MergeTreeMinMaxIndex & index); - ~MergeTreeMinMaxAggregator() override = default; + explicit MergeTreeIndexAggregatorMinMax(const MergeTreeIndexMinMax & index); + ~MergeTreeIndexAggregatorMinMax() override = default; bool empty() const override { return parallelogram.empty(); } MergeTreeIndexGranulePtr getGranuleAndReset() override; void update(const Block & block, size_t * pos, size_t limit) override; - const MergeTreeMinMaxIndex & index; + const MergeTreeIndexMinMax & index; std::vector parallelogram; }; -class MinMaxCondition : public IIndexCondition +class MergeTreeIndexConditionMinMax : public IMergeTreeIndexCondition { public: - MinMaxCondition( + MergeTreeIndexConditionMinMax( const SelectQueryInfo & query, const Context & context, - const MergeTreeMinMaxIndex & index); + const MergeTreeIndexMinMax & index); bool alwaysUnknownOrTrue() const override; bool mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granule) const override; - ~MinMaxCondition() override = default; + ~MergeTreeIndexConditionMinMax() override = default; private: - const MergeTreeMinMaxIndex & index; + const MergeTreeIndexMinMax & index; KeyCondition condition; }; -class MergeTreeMinMaxIndex : public IMergeTreeIndex +class MergeTreeIndexMinMax : public IMergeTreeIndex { public: - MergeTreeMinMaxIndex( + MergeTreeIndexMinMax( String name_, ExpressionActionsPtr expr_, const Names & columns_, @@ -74,12 +74,12 @@ public: size_t granularity_) : IMergeTreeIndex(name_, expr_, columns_, data_types_, header_, granularity_) {} - ~MergeTreeMinMaxIndex() override = default; + ~MergeTreeIndexMinMax() override = default; MergeTreeIndexGranulePtr createIndexGranule() const override; MergeTreeIndexAggregatorPtr createIndexAggregator() const override; - IndexConditionPtr createIndexCondition( + MergeTreeIndexConditionPtr createIndexCondition( const SelectQueryInfo & query, const Context & context) const override; bool mayBenefitFromIndexForIn(const ASTPtr & node) const override; diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndexReader.cpp b/dbms/src/Storages/MergeTree/MergeTreeIndexReader.cpp index 1557696874f..cd2725719a7 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeIndexReader.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexReader.cpp @@ -10,7 +10,7 @@ MergeTreeIndexReader::MergeTreeIndexReader( part->getFullPath() + index->getFileName(), ".idx", marks_count, all_mark_ranges, nullptr, false, nullptr, part->getFileSizeOrZero(index->getFileName() + ".idx"), 0, DBMS_DEFAULT_BUFFER_SIZE, - &part->storage.index_granularity_info, + &part->index_granularity_info, ReadBufferFromFileBase::ProfileCallback{}, CLOCK_MONOTONIC_COARSE) { stream.seekToStart(); diff --git a/dbms/src/Storages/MergeTree/MergeTreeSetSkippingIndex.cpp b/dbms/src/Storages/MergeTree/MergeTreeIndexSet.cpp similarity index 87% rename from dbms/src/Storages/MergeTree/MergeTreeSetSkippingIndex.cpp rename to dbms/src/Storages/MergeTree/MergeTreeIndexSet.cpp index 5bf06a1ca6d..9527e6a0a67 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeSetSkippingIndex.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexSet.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -21,18 +21,18 @@ namespace ErrorCodes const Field UNKNOWN_FIELD(3u); -MergeTreeSetIndexGranule::MergeTreeSetIndexGranule(const MergeTreeSetSkippingIndex & index) +MergeTreeIndexGranuleSet::MergeTreeIndexGranuleSet(const MergeTreeIndexSet & index) : IMergeTreeIndexGranule() , index(index) , block(index.header.cloneEmpty()) {} -MergeTreeSetIndexGranule::MergeTreeSetIndexGranule( - const MergeTreeSetSkippingIndex & index, MutableColumns && mutable_columns) +MergeTreeIndexGranuleSet::MergeTreeIndexGranuleSet( + const MergeTreeIndexSet & index, MutableColumns && mutable_columns) : IMergeTreeIndexGranule() , index(index) , block(index.header.cloneWithColumns(std::move(mutable_columns))) {} -void MergeTreeSetIndexGranule::serializeBinary(WriteBuffer & ostr) const +void MergeTreeIndexGranuleSet::serializeBinary(WriteBuffer & ostr) const { if (empty()) throw Exception( @@ -64,7 +64,7 @@ void MergeTreeSetIndexGranule::serializeBinary(WriteBuffer & ostr) const } } -void MergeTreeSetIndexGranule::deserializeBinary(ReadBuffer & istr) +void MergeTreeIndexGranuleSet::deserializeBinary(ReadBuffer & istr) { block.clear(); @@ -94,7 +94,7 @@ void MergeTreeSetIndexGranule::deserializeBinary(ReadBuffer & istr) } -MergeTreeSetIndexAggregator::MergeTreeSetIndexAggregator(const MergeTreeSetSkippingIndex & index) +MergeTreeIndexAggregatorSet::MergeTreeIndexAggregatorSet(const MergeTreeIndexSet & index) : index(index), columns(index.header.cloneEmptyColumns()) { ColumnRawPtrs column_ptrs; @@ -111,7 +111,7 @@ MergeTreeSetIndexAggregator::MergeTreeSetIndexAggregator(const MergeTreeSetSkipp columns = index.header.cloneEmptyColumns(); } -void MergeTreeSetIndexAggregator::update(const Block & block, size_t * pos, size_t limit) +void MergeTreeIndexAggregatorSet::update(const Block & block, size_t * pos, size_t limit) { if (*pos >= block.rows()) throw Exception( @@ -164,7 +164,7 @@ void MergeTreeSetIndexAggregator::update(const Block & block, size_t * pos, size } template -bool MergeTreeSetIndexAggregator::buildFilter( +bool MergeTreeIndexAggregatorSet::buildFilter( Method & method, const ColumnRawPtrs & column_ptrs, IColumn::Filter & filter, @@ -190,9 +190,9 @@ bool MergeTreeSetIndexAggregator::buildFilter( return has_new_data; } -MergeTreeIndexGranulePtr MergeTreeSetIndexAggregator::getGranuleAndReset() +MergeTreeIndexGranulePtr MergeTreeIndexAggregatorSet::getGranuleAndReset() { - auto granule = std::make_shared(index, std::move(columns)); + auto granule = std::make_shared(index, std::move(columns)); switch (data.type) { @@ -212,11 +212,11 @@ MergeTreeIndexGranulePtr MergeTreeSetIndexAggregator::getGranuleAndReset() } -SetIndexCondition::SetIndexCondition( +MergeTreeIndexConditionSet::MergeTreeIndexConditionSet( const SelectQueryInfo & query, const Context & context, - const MergeTreeSetSkippingIndex &index) - : IIndexCondition(), index(index) + const MergeTreeIndexSet &index) + : IMergeTreeIndexCondition(), index(index) { for (size_t i = 0, size = index.columns.size(); i < size; ++i) { @@ -253,14 +253,14 @@ SetIndexCondition::SetIndexCondition( actions = ExpressionAnalyzer(expression_ast, syntax_analyzer_result, context).getActions(true); } -bool SetIndexCondition::alwaysUnknownOrTrue() const +bool MergeTreeIndexConditionSet::alwaysUnknownOrTrue() const { return useless; } -bool SetIndexCondition::mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granule) const +bool MergeTreeIndexConditionSet::mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granule) const { - auto granule = std::dynamic_pointer_cast(idx_granule); + auto granule = std::dynamic_pointer_cast(idx_granule); if (!granule) throw Exception( "Set index condition got a granule with the wrong type.", ErrorCodes::LOGICAL_ERROR); @@ -276,7 +276,7 @@ bool SetIndexCondition::mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granule) const NullMap * null_map = nullptr; - if (auto * col_nullable = typeid_cast(column.get())) + if (auto * col_nullable = checkAndGetColumn(*column)) { col_uint8 = typeid_cast(&col_nullable->getNestedColumn()); null_map = &col_nullable->getNullMapData(); @@ -294,7 +294,7 @@ bool SetIndexCondition::mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granule) return false; } -void SetIndexCondition::traverseAST(ASTPtr & node) const +void MergeTreeIndexConditionSet::traverseAST(ASTPtr & node) const { if (operatorFromAST(node)) { @@ -309,7 +309,7 @@ void SetIndexCondition::traverseAST(ASTPtr & node) const node = std::make_shared(UNKNOWN_FIELD); } -bool SetIndexCondition::atomFromAST(ASTPtr & node) const +bool MergeTreeIndexConditionSet::atomFromAST(ASTPtr & node) const { /// Function, literal or column @@ -340,7 +340,7 @@ bool SetIndexCondition::atomFromAST(ASTPtr & node) const return false; } -bool SetIndexCondition::operatorFromAST(ASTPtr & node) const +bool MergeTreeIndexConditionSet::operatorFromAST(ASTPtr & node) const { /// Functions AND, OR, NOT. Replace with bit*. auto * func = node->as(); @@ -416,7 +416,7 @@ static bool checkAtomName(const String & name) return atoms.find(name) != atoms.end(); } -bool SetIndexCondition::checkASTUseless(const ASTPtr &node, bool atomic) const +bool MergeTreeIndexConditionSet::checkASTUseless(const ASTPtr &node, bool atomic) const { if (const auto * func = node->as()) { @@ -446,23 +446,23 @@ bool SetIndexCondition::checkASTUseless(const ASTPtr &node, bool atomic) const } -MergeTreeIndexGranulePtr MergeTreeSetSkippingIndex::createIndexGranule() const +MergeTreeIndexGranulePtr MergeTreeIndexSet::createIndexGranule() const { - return std::make_shared(*this); + return std::make_shared(*this); } -MergeTreeIndexAggregatorPtr MergeTreeSetSkippingIndex::createIndexAggregator() const +MergeTreeIndexAggregatorPtr MergeTreeIndexSet::createIndexAggregator() const { - return std::make_shared(*this); + return std::make_shared(*this); } -IndexConditionPtr MergeTreeSetSkippingIndex::createIndexCondition( +MergeTreeIndexConditionPtr MergeTreeIndexSet::createIndexCondition( const SelectQueryInfo & query, const Context & context) const { - return std::make_shared(query, context, *this); + return std::make_shared(query, context, *this); }; -bool MergeTreeSetSkippingIndex::mayBenefitFromIndexForIn(const ASTPtr &) const +bool MergeTreeIndexSet::mayBenefitFromIndexForIn(const ASTPtr &) const { return false; } @@ -506,7 +506,7 @@ std::unique_ptr setIndexCreator( header.insert(ColumnWithTypeAndName(column.type->createColumn(), column.type, column.name)); } - return std::make_unique( + return std::make_unique( node->name, std::move(unique_expr), columns, data_types, header, node->granularity, max_rows); } diff --git a/dbms/src/Storages/MergeTree/MergeTreeSetSkippingIndex.h b/dbms/src/Storages/MergeTree/MergeTreeIndexSet.h similarity index 69% rename from dbms/src/Storages/MergeTree/MergeTreeSetSkippingIndex.h rename to dbms/src/Storages/MergeTree/MergeTreeIndexSet.h index 61d409af589..04f4d2bec1e 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeSetSkippingIndex.h +++ b/dbms/src/Storages/MergeTree/MergeTreeIndexSet.h @@ -12,12 +12,12 @@ namespace DB { -class MergeTreeSetSkippingIndex; +class MergeTreeIndexSet; -struct MergeTreeSetIndexGranule : public IMergeTreeIndexGranule +struct MergeTreeIndexGranuleSet : public IMergeTreeIndexGranule { - explicit MergeTreeSetIndexGranule(const MergeTreeSetSkippingIndex & index); - MergeTreeSetIndexGranule(const MergeTreeSetSkippingIndex & index, MutableColumns && columns); + explicit MergeTreeIndexGranuleSet(const MergeTreeIndexSet & index); + MergeTreeIndexGranuleSet(const MergeTreeIndexSet & index, MutableColumns && columns); void serializeBinary(WriteBuffer & ostr) const override; void deserializeBinary(ReadBuffer & istr) override; @@ -25,17 +25,17 @@ struct MergeTreeSetIndexGranule : public IMergeTreeIndexGranule size_t size() const { return block.rows(); } bool empty() const override { return !size(); } - ~MergeTreeSetIndexGranule() override = default; + ~MergeTreeIndexGranuleSet() override = default; - const MergeTreeSetSkippingIndex & index; + const MergeTreeIndexSet & index; Block block; }; -struct MergeTreeSetIndexAggregator : IMergeTreeIndexAggregator +struct MergeTreeIndexAggregatorSet : IMergeTreeIndexAggregator { - explicit MergeTreeSetIndexAggregator(const MergeTreeSetSkippingIndex & index); - ~MergeTreeSetIndexAggregator() override = default; + explicit MergeTreeIndexAggregatorSet(const MergeTreeIndexSet & index); + ~MergeTreeIndexAggregatorSet() override = default; size_t size() const { return data.getTotalRowCount(); } bool empty() const override { return !size(); } @@ -55,26 +55,26 @@ private: size_t limit, ClearableSetVariants & variants) const; - const MergeTreeSetSkippingIndex & index; + const MergeTreeIndexSet & index; ClearableSetVariants data; Sizes key_sizes; MutableColumns columns; }; -class SetIndexCondition : public IIndexCondition +class MergeTreeIndexConditionSet : public IMergeTreeIndexCondition { public: - SetIndexCondition( + MergeTreeIndexConditionSet( const SelectQueryInfo & query, const Context & context, - const MergeTreeSetSkippingIndex & index); + const MergeTreeIndexSet & index); bool alwaysUnknownOrTrue() const override; bool mayBeTrueOnGranule(MergeTreeIndexGranulePtr idx_granule) const override; - ~SetIndexCondition() override = default; + ~MergeTreeIndexConditionSet() override = default; private: void traverseAST(ASTPtr & node) const; bool atomFromAST(ASTPtr & node) const; @@ -82,7 +82,7 @@ private: bool checkASTUseless(const ASTPtr &node, bool atomic = false) const; - const MergeTreeSetSkippingIndex & index; + const MergeTreeIndexSet & index; bool useless; std::set key_columns; @@ -91,10 +91,10 @@ private: }; -class MergeTreeSetSkippingIndex : public IMergeTreeIndex +class MergeTreeIndexSet : public IMergeTreeIndex { public: - MergeTreeSetSkippingIndex( + MergeTreeIndexSet( String name_, ExpressionActionsPtr expr_, const Names & columns_, @@ -104,12 +104,12 @@ public: size_t max_rows_) : IMergeTreeIndex(std::move(name_), std::move(expr_), columns_, data_types_, header_, granularity_), max_rows(max_rows_) {} - ~MergeTreeSetSkippingIndex() override = default; + ~MergeTreeIndexSet() override = default; MergeTreeIndexGranulePtr createIndexGranule() const override; MergeTreeIndexAggregatorPtr createIndexAggregator() const override; - IndexConditionPtr createIndexCondition( + MergeTreeIndexConditionPtr createIndexCondition( const SelectQueryInfo & query, const Context & context) const override; bool mayBenefitFromIndexForIn(const ASTPtr & node) const override; diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndices.cpp b/dbms/src/Storages/MergeTree/MergeTreeIndices.cpp index 74eb31ecd46..e19aafbd25d 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeIndices.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeIndices.cpp @@ -19,7 +19,7 @@ namespace ErrorCodes extern const int UNKNOWN_EXCEPTION; } -void MergeTreeIndexFactory::registerIndex(const std::string &name, Creator creator) +void MergeTreeIndexFactory::registerIndex(const std::string & name, Creator creator) { if (!indexes.emplace(name, std::move(creator)).second) throw Exception("MergeTreeIndexFactory: the Index creator name '" + name + "' is not unique", @@ -70,6 +70,11 @@ std::unique_ptr bloomFilterIndexCreator( std::shared_ptr node, const Context & context); +std::unique_ptr bloomFilterIndexCreatorNew( + const NamesAndTypesList & columns, + std::shared_ptr node, + const Context & context); + MergeTreeIndexFactory::MergeTreeIndexFactory() { @@ -77,6 +82,7 @@ MergeTreeIndexFactory::MergeTreeIndexFactory() registerIndex("set", setIndexCreator); registerIndex("ngrambf_v1", bloomFilterIndexCreator); registerIndex("tokenbf_v1", bloomFilterIndexCreator); + registerIndex("bloom_filter", bloomFilterIndexCreatorNew); } } diff --git a/dbms/src/Storages/MergeTree/MergeTreeIndices.h b/dbms/src/Storages/MergeTree/MergeTreeIndices.h index b6ee89d87ef..2a00c902810 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeIndices.h +++ b/dbms/src/Storages/MergeTree/MergeTreeIndices.h @@ -59,17 +59,17 @@ using MergeTreeIndexAggregators = std::vector; /// Condition on the index. -class IIndexCondition +class IMergeTreeIndexCondition { public: - virtual ~IIndexCondition() = default; + virtual ~IMergeTreeIndexCondition() = default; /// Checks if this index is useful for query. virtual bool alwaysUnknownOrTrue() const = 0; virtual bool mayBeTrueOnGranule(MergeTreeIndexGranulePtr granule) const = 0; }; -using IndexConditionPtr = std::shared_ptr; +using MergeTreeIndexConditionPtr = std::shared_ptr; /// Structure for storing basic index info like columns, expression, arguments, ... @@ -101,7 +101,7 @@ public: virtual MergeTreeIndexGranulePtr createIndexGranule() const = 0; virtual MergeTreeIndexAggregatorPtr createIndexAggregator() const = 0; - virtual IndexConditionPtr createIndexCondition( + virtual MergeTreeIndexConditionPtr createIndexCondition( const SelectQueryInfo & query_info, const Context & context) const = 0; String name; diff --git a/dbms/src/Storages/MergeTree/MergeTreeReader.cpp b/dbms/src/Storages/MergeTree/MergeTreeReader.cpp index fb5b341df1d..9f794f1a884 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeReader.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeReader.cpp @@ -173,7 +173,7 @@ void MergeTreeReader::addStreams(const String & name, const IDataType & type, all_mark_ranges, mark_cache, save_marks_in_cache, uncompressed_cache, data_part->getFileSizeOrZero(stream_name + DATA_FILE_EXTENSION), aio_threshold, max_read_buffer_size, - &storage.index_granularity_info, + &data_part->index_granularity_info, profile_callback, clock_type)); }; diff --git a/dbms/src/Storages/MergeTree/MergeTreeReaderStream.cpp b/dbms/src/Storages/MergeTree/MergeTreeReaderStream.cpp index b7eacabeee2..3dbfc61a00b 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeReaderStream.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeReaderStream.cpp @@ -20,7 +20,7 @@ MergeTreeReaderStream::MergeTreeReaderStream( MarkCache * mark_cache_, bool save_marks_in_cache_, UncompressedCache * uncompressed_cache, size_t file_size, size_t aio_threshold, size_t max_read_buffer_size, - const GranularityInfo * index_granularity_info_, + const MergeTreeIndexGranularityInfo * index_granularity_info_, const ReadBufferFromFileBase::ProfileCallback & profile_callback, clockid_t clock_type) : path_prefix(path_prefix_), data_file_extension(data_file_extension_), marks_count(marks_count_) , mark_cache(mark_cache_), save_marks_in_cache(save_marks_in_cache_) diff --git a/dbms/src/Storages/MergeTree/MergeTreeReaderStream.h b/dbms/src/Storages/MergeTree/MergeTreeReaderStream.h index ded0d03326a..d60689f1e91 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeReaderStream.h +++ b/dbms/src/Storages/MergeTree/MergeTreeReaderStream.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -13,14 +14,13 @@ namespace DB class MergeTreeReaderStream { public: - using GranularityInfo = MergeTreeData::IndexGranularityInfo; MergeTreeReaderStream( const String & path_prefix_, const String & data_file_extension_, size_t marks_count_, const MarkRanges & all_mark_ranges, MarkCache * mark_cache, bool save_marks_in_cache, UncompressedCache * uncompressed_cache, size_t file_size, size_t aio_threshold, size_t max_read_buffer_size, - const GranularityInfo * index_granularity_info_, + const MergeTreeIndexGranularityInfo * index_granularity_info_, const ReadBufferFromFileBase::ProfileCallback & profile_callback, clockid_t clock_type); void seekToMark(size_t index); @@ -44,7 +44,7 @@ private: bool save_marks_in_cache; MarkCache::MappedPtr marks; - const GranularityInfo * index_granularity_info; + const MergeTreeIndexGranularityInfo * index_granularity_info; std::unique_ptr cached_buffer; std::unique_ptr non_cached_buffer; diff --git a/dbms/src/Storages/MergeTree/MergeTreeSettings.h b/dbms/src/Storages/MergeTree/MergeTreeSettings.h index 08d886e4bd8..9bd58e77f9c 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeSettings.h +++ b/dbms/src/Storages/MergeTree/MergeTreeSettings.h @@ -77,9 +77,10 @@ struct MergeTreeSettings : public SettingsCollection M(SettingBool, use_minimalistic_part_header_in_zookeeper, false, "Store part header (checksums and columns) in a compact format and a single part znode instead of separate znodes (/columns and /checksums). This can dramatically reduce snapshot size in ZooKeeper. Before enabling check that all replicas support new format.") \ M(SettingUInt64, finished_mutations_to_keep, 100, "How many records about mutations that are done to keep. If zero, then keep all of them.") \ M(SettingUInt64, min_merge_bytes_to_use_direct_io, 10ULL * 1024 * 1024 * 1024, "Minimal amount of bytes to enable O_DIRECT in merge (0 - disabled).") \ - M(SettingUInt64, index_granularity_bytes, 0, "Approximate amount of bytes in single granule (0 - disabled).") \ + M(SettingUInt64, index_granularity_bytes, 10 * 1024 * 1024, "Approximate amount of bytes in single granule (0 - disabled).") \ M(SettingInt64, merge_with_ttl_timeout, 3600 * 24, "Minimal time in seconds, when merge with TTL can be repeated.") \ - M(SettingBool, write_final_mark, 1, "Write final mark after end of column (0 - disabled, do nothing if index_granularity_bytes=0)") + M(SettingBool, write_final_mark, 1, "Write final mark after end of column (0 - disabled, do nothing if index_granularity_bytes=0)") \ + M(SettingBool, enable_mixed_granularity_parts, 0, "Enable parts with adaptive and non adaptive granularity") DECLARE_SETTINGS_COLLECTION(LIST_OF_MERGE_TREE_SETTINGS) diff --git a/dbms/src/Storages/MergeTree/MergeTreeThreadSelectBlockInputStream.cpp b/dbms/src/Storages/MergeTree/MergeTreeThreadSelectBlockInputStream.cpp index 170a603ae23..1642b9da602 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeThreadSelectBlockInputStream.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeThreadSelectBlockInputStream.cpp @@ -29,9 +29,9 @@ MergeTreeThreadSelectBlockInputStream::MergeTreeThreadSelectBlockInputStream( /// round min_marks_to_read up to nearest multiple of block_size expressed in marks /// If granularity is adaptive it doesn't make sense /// Maybe it will make sence to add settings `max_block_size_bytes` - if (max_block_size_rows && !storage.index_granularity_info.is_adaptive) + if (max_block_size_rows && !storage.canUseAdaptiveGranularity()) { - size_t fixed_index_granularity = storage.index_granularity_info.fixed_index_granularity; + size_t fixed_index_granularity = storage.settings.index_granularity; min_marks_to_read = (min_marks_to_read_ * fixed_index_granularity + max_block_size_rows - 1) / max_block_size_rows * max_block_size_rows / fixed_index_granularity; } diff --git a/dbms/src/Storages/MergeTree/MergeTreeWhereOptimizer.cpp b/dbms/src/Storages/MergeTree/MergeTreeWhereOptimizer.cpp index 9bc95b889c9..4311fd027ef 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeWhereOptimizer.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeWhereOptimizer.cpp @@ -303,7 +303,7 @@ bool MergeTreeWhereOptimizer::isConstant(const ASTPtr & expr) const const auto column_name = expr->getColumnName(); if (expr->as() - || (block_with_constants.has(column_name) && block_with_constants.getByName(column_name).column->isColumnConst())) + || (block_with_constants.has(column_name) && isColumnConst(*block_with_constants.getByName(column_name).column))) return true; return false; diff --git a/dbms/src/Storages/MergeTree/MergedBlockOutputStream.cpp b/dbms/src/Storages/MergeTree/MergedBlockOutputStream.cpp index cc43232c486..8b38f1ff32e 100644 --- a/dbms/src/Storages/MergeTree/MergedBlockOutputStream.cpp +++ b/dbms/src/Storages/MergeTree/MergedBlockOutputStream.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -126,12 +127,12 @@ void MergedBlockOutputStream::writeSuffixAndFinalizePart( it->type->serializeBinaryBulkStateSuffix(serialize_settings, serialization_states[i]); } - if (with_final_mark) + if (with_final_mark && rows_count != 0) writeFinalMark(it->name, it->type, offset_columns, false, serialize_settings.path); } } - if (with_final_mark) + if (with_final_mark && rows_count != 0) index_granularity.appendMark(0); /// last mark /// Finish skip index serialization @@ -154,7 +155,7 @@ void MergedBlockOutputStream::writeSuffixAndFinalizePart( if (index_stream) { - if (with_final_mark) + if (with_final_mark && rows_count != 0) { for (size_t j = 0; j < index_columns.size(); ++j) { @@ -391,7 +392,7 @@ void MergedBlockOutputStream::writeImpl(const Block & block, const IColumn::Perm auto & stream = *skip_indices_streams[i]; size_t prev_pos = 0; - size_t current_mark = 0; + size_t skip_index_current_mark = 0; while (prev_pos < rows) { UInt64 limit = 0; @@ -401,7 +402,7 @@ void MergedBlockOutputStream::writeImpl(const Block & block, const IColumn::Perm } else { - limit = index_granularity.getMarkRows(current_mark); + limit = index_granularity.getMarkRows(skip_index_current_mark); if (skip_indices_aggregators[i]->empty()) { skip_indices_aggregators[i] = index->createIndexAggregator(); @@ -414,7 +415,7 @@ void MergedBlockOutputStream::writeImpl(const Block & block, const IColumn::Perm writeIntBinary(stream.compressed.offset(), stream.marks); /// Actually this numbers is redundant, but we have to store them /// to be compatible with normal .mrk2 file format - if (storage.index_granularity_info.is_adaptive) + if (storage.canUseAdaptiveGranularity()) writeIntBinary(1UL, stream.marks); } } @@ -434,7 +435,7 @@ void MergedBlockOutputStream::writeImpl(const Block & block, const IColumn::Perm } } prev_pos = pos; - current_mark++; + ++skip_index_current_mark; } } } diff --git a/dbms/src/Storages/MergeTree/RPNBuilder.h b/dbms/src/Storages/MergeTree/RPNBuilder.h index 6a557cb5f6a..d5244c3285d 100644 --- a/dbms/src/Storages/MergeTree/RPNBuilder.h +++ b/dbms/src/Storages/MergeTree/RPNBuilder.h @@ -24,10 +24,7 @@ public: using AtomFromASTFunc = std::function< bool(const ASTPtr & node, const Context & context, Block & block_with_constants, RPNElement & out)>; - RPNBuilder( - const SelectQueryInfo & query_info, - const Context & context_, - const AtomFromASTFunc & atomFromAST_) + RPNBuilder(const SelectQueryInfo & query_info, const Context & context_, const AtomFromASTFunc & atomFromAST_) : context(context_), atomFromAST(atomFromAST_) { /** Evaluation of expressions that depend only on constants. diff --git a/dbms/src/Storages/MergeTree/ReplicatedMergeTreePartCheckThread.cpp b/dbms/src/Storages/MergeTree/ReplicatedMergeTreePartCheckThread.cpp index b06dea30052..045aa8a6461 100644 --- a/dbms/src/Storages/MergeTree/ReplicatedMergeTreePartCheckThread.cpp +++ b/dbms/src/Storages/MergeTree/ReplicatedMergeTreePartCheckThread.cpp @@ -181,7 +181,7 @@ void ReplicatedMergeTreePartCheckThread::searchForMissingPart(const String & par } -void ReplicatedMergeTreePartCheckThread::checkPart(const String & part_name) +CheckResult ReplicatedMergeTreePartCheckThread::checkPart(const String & part_name) { LOG_WARNING(log, "Checking part " << part_name); ProfileEvents::increment(ProfileEvents::ReplicatedPartChecks); @@ -197,6 +197,7 @@ void ReplicatedMergeTreePartCheckThread::checkPart(const String & part_name) if (!part) { searchForMissingPart(part_name); + return {part_name, false, "Part is missing, will search for it"}; } /// We have this part, and it's active. We will check whether we need this part and whether it has the right data. else if (part->name == part_name) @@ -242,7 +243,7 @@ void ReplicatedMergeTreePartCheckThread::checkPart(const String & part_name) if (need_stop) { LOG_INFO(log, "Checking part was cancelled."); - return; + return {part_name, false, "Checking part was cancelled"}; } LOG_INFO(log, "Part " << part_name << " looks good."); @@ -253,13 +254,15 @@ void ReplicatedMergeTreePartCheckThread::checkPart(const String & part_name) tryLogCurrentException(log, __PRETTY_FUNCTION__); - LOG_ERROR(log, "Part " << part_name << " looks broken. Removing it and queueing a fetch."); + String message = "Part " + part_name + " looks broken. Removing it and queueing a fetch."; + LOG_ERROR(log, message); ProfileEvents::increment(ProfileEvents::ReplicatedPartChecksFailed); storage.removePartAndEnqueueFetch(part_name); /// Delete part locally. storage.forgetPartAndMoveToDetached(part, "broken"); + return {part_name, false, message}; } } else if (part->modification_time + MAX_AGE_OF_LOCAL_PART_THAT_WASNT_ADDED_TO_ZOOKEEPER < time(nullptr)) @@ -269,8 +272,10 @@ void ReplicatedMergeTreePartCheckThread::checkPart(const String & part_name) /// Therefore, delete only if the part is old (not very reliable). ProfileEvents::increment(ProfileEvents::ReplicatedPartChecksFailed); - LOG_ERROR(log, "Unexpected part " << part_name << " in filesystem. Removing."); + String message = "Unexpected part " + part_name + " in filesystem. Removing."; + LOG_ERROR(log, message); storage.forgetPartAndMoveToDetached(part, "unexpected"); + return {part_name, false, message}; } else { @@ -290,6 +295,8 @@ void ReplicatedMergeTreePartCheckThread::checkPart(const String & part_name) /// In the worst case, errors will still appear `old_parts_lifetime` seconds in error log until the part is removed as the old one. LOG_WARNING(log, "We have part " << part->name << " covering part " << part_name); } + + return {part_name, true, ""}; } diff --git a/dbms/src/Storages/MergeTree/ReplicatedMergeTreePartCheckThread.h b/dbms/src/Storages/MergeTree/ReplicatedMergeTreePartCheckThread.h index 432fb0f4bb6..322ee593c46 100644 --- a/dbms/src/Storages/MergeTree/ReplicatedMergeTreePartCheckThread.h +++ b/dbms/src/Storages/MergeTree/ReplicatedMergeTreePartCheckThread.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace DB { @@ -66,12 +67,12 @@ public: /// Get the number of parts in the queue for check. size_t size() const; - + /// Check part by name + CheckResult checkPart(const String & part_name); private: void run(); - void checkPart(const String & part_name); void searchForMissingPart(const String & part_name); StorageReplicatedMergeTree & storage; diff --git a/dbms/src/Storages/MergeTree/ReplicatedMergeTreeTableMetadata.cpp b/dbms/src/Storages/MergeTree/ReplicatedMergeTreeTableMetadata.cpp index b122785c5fd..10f77358b7d 100644 --- a/dbms/src/Storages/MergeTree/ReplicatedMergeTreeTableMetadata.cpp +++ b/dbms/src/Storages/MergeTree/ReplicatedMergeTreeTableMetadata.cpp @@ -28,7 +28,7 @@ ReplicatedMergeTreeTableMetadata::ReplicatedMergeTreeTableMetadata(const MergeTr date_column = data.minmax_idx_columns[data.minmax_idx_date_column_pos]; sampling_expression = formattedAST(data.sample_by_ast); - index_granularity = data.index_granularity_info.fixed_index_granularity; + index_granularity = data.settings.index_granularity; merging_params_mode = static_cast(data.merging_params.mode); sign_column = data.merging_params.sign_column; @@ -45,9 +45,12 @@ ReplicatedMergeTreeTableMetadata::ReplicatedMergeTreeTableMetadata(const MergeTr if (data.format_version >= MERGE_TREE_DATA_MIN_FORMAT_VERSION_WITH_CUSTOM_PARTITIONING) partition_key = formattedAST(MergeTreeData::extractKeyExpressionList(data.partition_by_ast)); - skip_indices = data.getIndices().toString(); - index_granularity_bytes = data.index_granularity_info.index_granularity_bytes; ttl_table = formattedAST(data.ttl_table_ast); + skip_indices = data.getIndices().toString(); + if (data.canUseAdaptiveGranularity()) + index_granularity_bytes = data.settings.index_granularity_bytes; + else + index_granularity_bytes = 0; } void ReplicatedMergeTreeTableMetadata::write(WriteBuffer & out) const @@ -98,8 +101,8 @@ void ReplicatedMergeTreeTableMetadata::read(ReadBuffer & in) if (in.eof()) data_format_version = 0; - else - in >> "data format version: " >> data_format_version.toUnderType() >> "\n"; + else if (checkString("data format version: ", in)) + in >> data_format_version.toUnderType() >> "\n"; if (data_format_version >= MERGE_TREE_DATA_MIN_FORMAT_VERSION_WITH_CUSTOM_PARTITIONING) in >> "partition key: " >> partition_key >> "\n"; @@ -107,16 +110,19 @@ void ReplicatedMergeTreeTableMetadata::read(ReadBuffer & in) if (checkString("sorting key: ", in)) in >> sorting_key >> "\n"; + if (checkString("ttl: ", in)) + in >> ttl_table >> "\n"; + if (checkString("indices: ", in)) in >> skip_indices >> "\n"; if (checkString("granularity bytes: ", in)) + { in >> index_granularity_bytes >> "\n"; + index_granularity_bytes_found_in_zk = true; + } else index_granularity_bytes = 0; - - if (checkString("ttl: ", in)) - in >> ttl_table >> "\n"; } ReplicatedMergeTreeTableMetadata ReplicatedMergeTreeTableMetadata::parse(const String & s) @@ -229,7 +235,7 @@ ReplicatedMergeTreeTableMetadata::checkAndFindDiff(const ReplicatedMergeTreeTabl ErrorCodes::METADATA_MISMATCH); } - if (index_granularity_bytes != from_zk.index_granularity_bytes) + if (from_zk.index_granularity_bytes_found_in_zk && index_granularity_bytes != from_zk.index_granularity_bytes) throw Exception("Existing table metadata in ZooKeeper differs in index granularity bytes." " Stored in ZooKeeper: " + DB::toString(from_zk.index_granularity_bytes) + ", local: " + DB::toString(index_granularity_bytes), diff --git a/dbms/src/Storages/MergeTree/ReplicatedMergeTreeTableMetadata.h b/dbms/src/Storages/MergeTree/ReplicatedMergeTreeTableMetadata.h index dcf558bd1d0..1a2df98f4f7 100644 --- a/dbms/src/Storages/MergeTree/ReplicatedMergeTreeTableMetadata.h +++ b/dbms/src/Storages/MergeTree/ReplicatedMergeTreeTableMetadata.h @@ -26,8 +26,8 @@ struct ReplicatedMergeTreeTableMetadata String partition_key; String sorting_key; String skip_indices; - UInt64 index_granularity_bytes; String ttl_table; + UInt64 index_granularity_bytes; ReplicatedMergeTreeTableMetadata() = default; explicit ReplicatedMergeTreeTableMetadata(const MergeTreeData & data); @@ -53,6 +53,9 @@ struct ReplicatedMergeTreeTableMetadata }; Diff checkAndFindDiff(const ReplicatedMergeTreeTableMetadata & from_zk, bool allow_alter) const; + +private: + bool index_granularity_bytes_found_in_zk = false; }; } diff --git a/dbms/src/Storages/MergeTree/StorageFromMergeTreeDataPart.h b/dbms/src/Storages/MergeTree/StorageFromMergeTreeDataPart.h index 53573ed523a..833bad47ecd 100644 --- a/dbms/src/Storages/MergeTree/StorageFromMergeTreeDataPart.h +++ b/dbms/src/Storages/MergeTree/StorageFromMergeTreeDataPart.h @@ -17,6 +17,7 @@ class StorageFromMergeTreeDataPart : public ext::shared_ptr_helperstorage.getTableName() + " (part " + part->name + ")"; } + String getDatabaseName() const override { return part->storage.getDatabaseName(); } BlockInputStreams read( const Names & column_names, diff --git a/dbms/src/Storages/MergeTree/checkDataPart.cpp b/dbms/src/Storages/MergeTree/checkDataPart.cpp index bf1bfb2cafa..2ae83b5076a 100644 --- a/dbms/src/Storages/MergeTree/checkDataPart.cpp +++ b/dbms/src/Storages/MergeTree/checkDataPart.cpp @@ -53,6 +53,20 @@ public: private: ReadBufferFromFile mrk_file_buf; + + std::pair readMarkFromFile() + { + size_t mrk_rows; + MarkInCompressedFile mrk_mark; + readIntBinary(mrk_mark.offset_in_compressed_file, mrk_hashing_buf); + readIntBinary(mrk_mark.offset_in_decompressed_block, mrk_hashing_buf); + if (mrk_file_extension == ".mrk2") + readIntBinary(mrk_rows, mrk_hashing_buf); + else + mrk_rows = index_granularity.getMarkRows(mark_position); + + return {mrk_mark, mrk_rows}; + } public: HashingReadBuffer mrk_hashing_buf; @@ -76,17 +90,10 @@ public: , mrk_hashing_buf(mrk_file_buf) {} - void assertMark() + void assertMark(bool only_read=false) { - MarkInCompressedFile mrk_mark; - readIntBinary(mrk_mark.offset_in_compressed_file, mrk_hashing_buf); - readIntBinary(mrk_mark.offset_in_decompressed_block, mrk_hashing_buf); - size_t mrk_rows; - if (mrk_file_extension == ".mrk2") - readIntBinary(mrk_rows, mrk_hashing_buf); - else - mrk_rows = index_granularity.getMarkRows(mark_position); + auto [mrk_mark, mrk_rows] = readMarkFromFile(); bool has_alternative_mark = false; MarkInCompressedFile alternative_data_mark = {}; MarkInCompressedFile data_mark = {}; @@ -120,7 +127,7 @@ public: data_mark.offset_in_compressed_file = compressed_hashing_buf.count() - uncompressing_buf.getSizeCompressed(); data_mark.offset_in_decompressed_block = uncompressed_hashing_buf.offset(); - if (mrk_mark != data_mark || mrk_rows != index_granularity.getMarkRows(mark_position)) + if (!only_read && (mrk_mark != data_mark || mrk_rows != index_granularity.getMarkRows(mark_position))) throw Exception("Incorrect mark: " + data_mark.toStringWithRows(index_granularity.getMarkRows(mark_position)) + (has_alternative_mark ? " or " + alternative_data_mark.toString() : "") + " in data, " + mrk_mark.toStringWithRows(mrk_rows) + " in " + mrk_file_path + " file", ErrorCodes::INCORRECT_MARK); @@ -136,6 +143,12 @@ public: + toString(compressed_hashing_buf.count()) + " (compressed), " + toString(uncompressed_hashing_buf.count()) + " (uncompressed)", ErrorCodes::CORRUPTED_DATA); + if (index_granularity.hasFinalMark()) + { + auto final_mark_rows = readMarkFromFile().second; + if (final_mark_rows != 0) + throw Exception("Incorrect final mark at the end of " + mrk_file_path + " expected 0 rows, got " + toString(final_mark_rows), ErrorCodes::CORRUPTED_DATA); + } if (!mrk_hashing_buf.eof()) throw Exception("EOF expected in " + mrk_file_path + " file" + " at position " @@ -319,20 +332,35 @@ MergeTreeData::DataPart::Checksums checkDataPart( size_t column_size = 0; size_t mark_num = 0; + IDataType::DeserializeBinaryBulkStatePtr state; + IDataType::DeserializeBinaryBulkSettings settings; + settings.getter = [&](const IDataType::SubstreamPath & substream_path) + { + String file_name = IDataType::getFileNameForStream(name_type.name, substream_path); + auto & stream = streams.try_emplace(file_name, path, file_name, ".bin", mrk_file_extension, adaptive_index_granularity).first->second; + return &stream.uncompressed_hashing_buf; + }; + + /// Prefixes have to be read before data because first mark points after prefix + name_type.type->deserializeBinaryBulkStatePrefix(settings, state); + while (true) { - IDataType::DeserializeBinaryBulkSettings settings; /// Check that mark points to current position in file. bool marks_eof = false; name_type.type->enumerateStreams([&](const IDataType::SubstreamPath & substream_path) { String file_name = IDataType::getFileNameForStream(name_type.name, substream_path); + auto & stream = streams.try_emplace(file_name, path, file_name, ".bin", mrk_file_extension, adaptive_index_granularity).first->second; try { + /// LowCardinality dictionary column is not read monotonically, so marks maybe inconsistent with + /// offset position in file. So we just read data and marks file, but doesn't check marks equality. + bool only_read = !substream_path.empty() && substream_path.back().type == IDataType::Substream::DictionaryKeys; if (!stream.mrk_hashing_buf.eof()) - stream.assertMark(); + stream.assertMark(only_read); else marks_eof = true; } @@ -352,17 +380,6 @@ MergeTreeData::DataPart::Checksums checkDataPart( /// NOTE Shared array sizes of Nested columns are read more than once. That's Ok. MutableColumnPtr tmp_column = name_type.type->createColumn(); - settings.getter = [&](const IDataType::SubstreamPath & substream_path) - { - String file_name = IDataType::getFileNameForStream(name_type.name, substream_path); - auto stream_it = streams.find(file_name); - if (stream_it == streams.end()) - throw Exception("Logical error: cannot find stream " + file_name, ErrorCodes::LOGICAL_ERROR); - return &stream_it->second.uncompressed_hashing_buf; - }; - - IDataType::DeserializeBinaryBulkStatePtr state; - name_type.type->deserializeBinaryBulkStatePrefix(settings, state); name_type.type->deserializeBinaryBulkWithMultipleStreams(*tmp_column, rows_after_mark, settings, state); size_t read_size = tmp_column->size(); @@ -433,7 +450,7 @@ MergeTreeData::DataPart::Checksums checkDataPart( return checkDataPart( data_part->getFullPath(), data_part->index_granularity, - data_part->storage.index_granularity_info.marks_file_extension, + data_part->index_granularity_info.marks_file_extension, require_checksums, primary_key_data_types, indices, diff --git a/dbms/src/Storages/MergeTree/registerStorageMergeTree.cpp b/dbms/src/Storages/MergeTree/registerStorageMergeTree.cpp index b23a2eedc0e..138e7c14f9d 100644 --- a/dbms/src/Storages/MergeTree/registerStorageMergeTree.cpp +++ b/dbms/src/Storages/MergeTree/registerStorageMergeTree.cpp @@ -2,8 +2,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/dbms/src/Storages/StorageBuffer.cpp b/dbms/src/Storages/StorageBuffer.cpp index 24e1ecef2e3..3c334b2a48b 100644 --- a/dbms/src/Storages/StorageBuffer.cpp +++ b/dbms/src/Storages/StorageBuffer.cpp @@ -55,17 +55,17 @@ namespace ErrorCodes } -StorageBuffer::StorageBuffer(const std::string & name_, const ColumnsDescription & columns_, +StorageBuffer::StorageBuffer(const std::string & database_name_, const std::string & table_name_, const ColumnsDescription & columns_, Context & context_, size_t num_shards_, const Thresholds & min_thresholds_, const Thresholds & max_thresholds_, const String & destination_database_, const String & destination_table_, bool allow_materialized_) : IStorage{columns_}, - name(name_), global_context(context_), + table_name(table_name_), database_name(database_name_), global_context(context_), num_shards(num_shards_), buffers(num_shards_), min_thresholds(min_thresholds_), max_thresholds(max_thresholds_), destination_database(destination_database_), destination_table(destination_table_), no_destination(destination_database.empty() && destination_table.empty()), - allow_materialized(allow_materialized_), log(&Logger::get("StorageBuffer (" + name + ")")) + allow_materialized(allow_materialized_), log(&Logger::get("StorageBuffer (" + table_name + ")")) { } @@ -692,7 +692,7 @@ void StorageBuffer::flushThread() } -void StorageBuffer::alter(const AlterCommands & params, const String & database_name, const String & table_name, const Context & context, TableStructureWriteLockHolder & table_lock_holder) +void StorageBuffer::alter(const AlterCommands & params, const String & database_name_, const String & table_name_, const Context & context, TableStructureWriteLockHolder & table_lock_holder) { lockStructureExclusively(table_lock_holder, context.getCurrentQueryId()); @@ -702,7 +702,7 @@ void StorageBuffer::alter(const AlterCommands & params, const String & database_ auto new_columns = getColumns(); auto new_indices = getIndices(); params.apply(new_columns); - context.getDatabase(database_name)->alterTable(context, table_name, new_columns, new_indices, {}); + context.getDatabase(database_name_)->alterTable(context, table_name_, new_columns, new_indices, {}); setColumns(std::move(new_columns)); } @@ -741,6 +741,7 @@ void registerStorageBuffer(StorageFactory & factory) UInt64 max_bytes = applyVisitor(FieldVisitorConvertToNumber(), engine_args[8]->as().value); return StorageBuffer::create( + args.database_name, args.table_name, args.columns, args.context, num_buckets, diff --git a/dbms/src/Storages/StorageBuffer.h b/dbms/src/Storages/StorageBuffer.h index 9e7127f8417..4c317a7a102 100644 --- a/dbms/src/Storages/StorageBuffer.h +++ b/dbms/src/Storages/StorageBuffer.h @@ -52,7 +52,8 @@ public: }; std::string getName() const override { return "Buffer"; } - std::string getTableName() const override { return name; } + std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } QueryProcessingStage::Enum getQueryProcessingStage(const Context & context) const override; @@ -71,7 +72,7 @@ public: void shutdown() override; bool optimize(const ASTPtr & query, const ASTPtr & partition, bool final, bool deduplicate, const Context & context) override; - void rename(const String & /*new_path_to_db*/, const String & /*new_database_name*/, const String & new_table_name) override { name = new_table_name; } + void rename(const String & /*new_path_to_db*/, const String & new_database_name, const String & new_table_name) override { table_name = new_table_name; database_name = new_database_name; } bool supportsSampling() const override { return true; } bool supportsPrewhere() const override @@ -94,7 +95,8 @@ public: const Context & context, TableStructureWriteLockHolder & table_lock_holder) override; private: - String name; + String table_name; + String database_name; Context global_context; @@ -138,7 +140,7 @@ protected: /** num_shards - the level of internal parallelism (the number of independent buffers) * The buffer is flushed if all minimum thresholds or at least one of the maximum thresholds are exceeded. */ - StorageBuffer(const std::string & name_, const ColumnsDescription & columns_, + StorageBuffer(const std::string & database_name_, const std::string & table_name_, const ColumnsDescription & columns_, Context & context_, size_t num_shards_, const Thresholds & min_thresholds_, const Thresholds & max_thresholds_, const String & destination_database_, const String & destination_table_, bool allow_materialized_); diff --git a/dbms/src/Storages/StorageCatBoostPool.cpp b/dbms/src/Storages/StorageCatBoostPool.cpp index 1258ebec7e2..a9e2acedcce 100644 --- a/dbms/src/Storages/StorageCatBoostPool.cpp +++ b/dbms/src/Storages/StorageCatBoostPool.cpp @@ -90,11 +90,16 @@ static void checkCreationIsAllowed(const String & base_path, const String & path } -StorageCatBoostPool::StorageCatBoostPool(const Context & context, - String column_description_file_name_, - String data_description_file_name_) - : column_description_file_name(std::move(column_description_file_name_)), - data_description_file_name(std::move(data_description_file_name_)) +StorageCatBoostPool::StorageCatBoostPool( + const String & database_name_, + const String & table_name_, + const Context & context, + String column_description_file_name_, + String data_description_file_name_) + : table_name(table_name_) + , database_name(database_name_) + , column_description_file_name(std::move(column_description_file_name_)) + , data_description_file_name(std::move(data_description_file_name_)) { auto base_path = canonicalPath(context.getPath()); column_description_file_name = resolvePath(base_path, std::move(column_description_file_name)); @@ -254,12 +259,12 @@ void StorageCatBoostPool::createSampleBlockAndColumns() /// Order is important: first numeric columns, then categorial, then all others. for (const auto & column : num_columns) - columns.add(DB::ColumnDescription(column.name, column.type)); + columns.add(DB::ColumnDescription(column.name, column.type, false)); for (const auto & column : cat_columns) - columns.add(DB::ColumnDescription(column.name, column.type)); + columns.add(DB::ColumnDescription(column.name, column.type, false)); for (const auto & column : other_columns) { - DB::ColumnDescription column_desc(column.name, column.type); + DB::ColumnDescription column_desc(column.name, column.type, false); /// We assign Materialized kind to the column so that it doesn't show in SELECT *. /// Because the table is readonly, we do not need default expression. column_desc.default_desc.kind = ColumnDefaultKind::Materialized; @@ -270,7 +275,7 @@ void StorageCatBoostPool::createSampleBlockAndColumns() { if (!desc.alias.empty()) { - DB::ColumnDescription column(desc.alias, get_type(desc.column_type)); + DB::ColumnDescription column(desc.alias, get_type(desc.column_type), false); column.default_desc.kind = ColumnDefaultKind::Alias; column.default_desc.expression = std::make_shared(desc.column_name); columns.add(std::move(column)); diff --git a/dbms/src/Storages/StorageCatBoostPool.h b/dbms/src/Storages/StorageCatBoostPool.h index 54a7bf1b655..0cc457fabc0 100644 --- a/dbms/src/Storages/StorageCatBoostPool.h +++ b/dbms/src/Storages/StorageCatBoostPool.h @@ -11,8 +11,8 @@ class StorageCatBoostPool : public ext::shared_ptr_helper, { public: std::string getName() const override { return "CatBoostPool"; } - std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } BlockInputStreams read(const Names & column_names, const SelectQueryInfo & query_info, @@ -23,6 +23,7 @@ public: private: String table_name; + String database_name; String column_description_file_name; String data_description_file_name; @@ -75,7 +76,7 @@ private: void createSampleBlockAndColumns(); protected: - StorageCatBoostPool(const Context & context, String column_description_file_name, String data_description_file_name); + StorageCatBoostPool(const String & database_name_, const String & table_name_, const Context & context, String column_description_file_name, String data_description_file_name); }; } diff --git a/dbms/src/Storages/StorageDictionary.cpp b/dbms/src/Storages/StorageDictionary.cpp index ea9276766ba..923a309f1f6 100644 --- a/dbms/src/Storages/StorageDictionary.cpp +++ b/dbms/src/Storages/StorageDictionary.cpp @@ -24,12 +24,14 @@ namespace ErrorCodes StorageDictionary::StorageDictionary( + const String & database_name_, const String & table_name_, const ColumnsDescription & columns_, const Context & context, bool attach, const String & dictionary_name_) : IStorage{columns_}, table_name(table_name_), + database_name(database_name_), dictionary_name(dictionary_name_), logger(&Poco::Logger::get("StorageDictionary")) { @@ -104,7 +106,7 @@ void registerStorageDictionary(StorageFactory & factory) String dictionary_name = args.engine_args[0]->as().value.safeGet(); return StorageDictionary::create( - args.table_name, args.columns, args.context, args.attach, dictionary_name); + args.database_name, args.table_name, args.columns, args.context, args.attach, dictionary_name); }); } diff --git a/dbms/src/Storages/StorageDictionary.h b/dbms/src/Storages/StorageDictionary.h index 96798022ebf..cf5fd647e74 100644 --- a/dbms/src/Storages/StorageDictionary.h +++ b/dbms/src/Storages/StorageDictionary.h @@ -24,6 +24,8 @@ class StorageDictionary : public ext::shared_ptr_helper, publ public: std::string getName() const override { return "Dictionary"; } std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } + BlockInputStreams read(const Names & column_names, const SelectQueryInfo & query_info, const Context & context, @@ -58,13 +60,16 @@ private: using Ptr = MultiVersion::Version; String table_name; + String database_name; String dictionary_name; Poco::Logger * logger; void checkNamesAndTypesCompatibleWithDictionary(const DictionaryStructure & dictionary_structure) const; protected: - StorageDictionary(const String & table_name_, + StorageDictionary( + const String & database_name_, + const String & table_name_, const ColumnsDescription & columns_, const Context & context, bool attach, diff --git a/dbms/src/Storages/StorageDistributed.cpp b/dbms/src/Storages/StorageDistributed.cpp index 826407e0599..27ceb1f45db 100644 --- a/dbms/src/Storages/StorageDistributed.cpp +++ b/dbms/src/Storages/StorageDistributed.cpp @@ -189,7 +189,7 @@ StorageDistributed::StorageDistributed( const ASTPtr & sharding_key_, const String & data_path_, bool attach) - : IStorage{columns_}, table_name(table_name), + : IStorage{columns_}, table_name(table_name), database_name(database_name), remote_database(remote_database_), remote_table(remote_table_), global_context(context_), cluster_name(global_context.getMacros()->expand(cluster_name_)), has_sharding_key(sharding_key_), sharding_key_expr(sharding_key_ ? buildShardingKeyExpression(sharding_key_, global_context, getColumns().getAllPhysical(), false) : nullptr), @@ -343,7 +343,7 @@ BlockOutputStreamPtr StorageDistributed::write(const ASTPtr &, const Context & c void StorageDistributed::alter( - const AlterCommands & params, const String & database_name, const String & current_table_name, + const AlterCommands & params, const String & current_database_name, const String & current_table_name, const Context & context, TableStructureWriteLockHolder & table_lock_holder) { lockStructureExclusively(table_lock_holder, context.getCurrentQueryId()); @@ -351,7 +351,7 @@ void StorageDistributed::alter( auto new_columns = getColumns(); auto new_indices = getIndices(); params.apply(new_columns); - context.getDatabase(database_name)->alterTable(context, current_table_name, new_columns, new_indices, {}); + context.getDatabase(current_database_name)->alterTable(context, current_table_name, new_columns, new_indices, {}); setColumns(std::move(new_columns)); } diff --git a/dbms/src/Storages/StorageDistributed.h b/dbms/src/Storages/StorageDistributed.h index fee3ba78d8d..86fe80f575f 100644 --- a/dbms/src/Storages/StorageDistributed.h +++ b/dbms/src/Storages/StorageDistributed.h @@ -52,6 +52,8 @@ public: std::string getName() const override { return "Distributed"; } std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } + bool supportsSampling() const override { return true; } bool supportsFinal() const override { return true; } bool supportsPrewhere() const override { return true; } @@ -79,7 +81,7 @@ public: /// Removes temporary data in local filesystem. void truncate(const ASTPtr &, const Context &) override; - void rename(const String & /*new_path_to_db*/, const String & /*new_database_name*/, const String & new_table_name) override { table_name = new_table_name; } + void rename(const String & /*new_path_to_db*/, const String & new_database_name, const String & new_table_name) override { table_name = new_table_name; database_name = new_database_name; } /// in the sub-tables, you need to manually add and delete columns /// the structure of the sub-table is not checked void alter( @@ -113,6 +115,7 @@ public: ActionLock getActionLock(StorageActionBlockType type) override; String table_name; + String database_name; String remote_database; String remote_table; ASTPtr remote_table_function_ptr; diff --git a/dbms/src/Storages/StorageFile.cpp b/dbms/src/Storages/StorageFile.cpp index 28c81c4902f..35bc1747dee 100644 --- a/dbms/src/Storages/StorageFile.cpp +++ b/dbms/src/Storages/StorageFile.cpp @@ -68,12 +68,13 @@ StorageFile::StorageFile( const std::string & table_path_, int table_fd_, const std::string & db_dir_path, + const std::string & database_name_, const std::string & table_name_, const std::string & format_name_, const ColumnsDescription & columns_, Context & context_) : IStorage(columns_), - table_name(table_name_), format_name(format_name_), context_global(context_), table_fd(table_fd_) + table_name(table_name_), database_name(database_name_), format_name(format_name_), context_global(context_), table_fd(table_fd_) { if (table_fd < 0) /// Will use file { @@ -265,7 +266,7 @@ void StorageFile::drop() } -void StorageFile::rename(const String & new_path_to_db, const String & /*new_database_name*/, const String & new_table_name) +void StorageFile::rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) { if (!is_db_table) throw Exception("Can't rename table '" + table_name + "' binded to user-defined file (or FD)", ErrorCodes::DATABASE_ACCESS_DENIED); @@ -277,6 +278,8 @@ void StorageFile::rename(const String & new_path_to_db, const String & /*new_dat Poco::File(path).renameTo(path_new); path = std::move(path_new); + table_name = new_table_name; + database_name = new_database_name; } @@ -327,7 +330,7 @@ void registerStorageFile(StorageFactory & factory) return StorageFile::create( source_path, source_fd, args.data_path, - args.table_name, format_name, args.columns, + args.database_name, args.table_name, format_name, args.columns, args.context); }); } diff --git a/dbms/src/Storages/StorageFile.h b/dbms/src/Storages/StorageFile.h index eb74ad615a7..cc5878520ce 100644 --- a/dbms/src/Storages/StorageFile.h +++ b/dbms/src/Storages/StorageFile.h @@ -21,15 +21,9 @@ class StorageFileBlockOutputStream; class StorageFile : public ext::shared_ptr_helper, public IStorage { public: - std::string getName() const override - { - return "File"; - } - - std::string getTableName() const override - { - return table_name; - } + std::string getName() const override { return "File"; } + std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } BlockInputStreams read( const Names & column_names, @@ -62,14 +56,15 @@ protected: const std::string & table_path_, int table_fd_, const std::string & db_dir_path, + const std::string & database_name_, const std::string & table_name_, const std::string & format_name_, const ColumnsDescription & columns_, Context & context_); private: - std::string table_name; + std::string database_name; std::string format_name; Context & context_global; diff --git a/dbms/src/Storages/StorageHDFS.cpp b/dbms/src/Storages/StorageHDFS.cpp index d7bd942527b..8c87f4ccd6a 100644 --- a/dbms/src/Storages/StorageHDFS.cpp +++ b/dbms/src/Storages/StorageHDFS.cpp @@ -26,6 +26,7 @@ namespace ErrorCodes } StorageHDFS::StorageHDFS(const String & uri_, + const std::string & database_name_, const std::string & table_name_, const String & format_name_, const ColumnsDescription & columns_, @@ -34,6 +35,7 @@ StorageHDFS::StorageHDFS(const String & uri_, , uri(uri_) , format_name(format_name_) , table_name(table_name_) + , database_name(database_name_) , context(context_) { } @@ -144,7 +146,11 @@ BlockInputStreams StorageHDFS::read( max_block_size)}; } -void StorageHDFS::rename(const String & /*new_path_to_db*/, const String & /*new_database_name*/, const String & /*new_table_name*/) {} +void StorageHDFS::rename(const String & /*new_path_to_db*/, const String & new_database_name, const String & new_table_name) +{ + table_name = new_table_name; + database_name = new_database_name; +} BlockOutputStreamPtr StorageHDFS::write(const ASTPtr & /*query*/, const Context & /*context*/) { @@ -169,7 +175,7 @@ void registerStorageHDFS(StorageFactory & factory) String format_name = engine_args[1]->as().value.safeGet(); - return StorageHDFS::create(url, args.table_name, format_name, args.columns, args.context); + return StorageHDFS::create(url, args.database_name, args.table_name, format_name, args.columns, args.context); }); } diff --git a/dbms/src/Storages/StorageHDFS.h b/dbms/src/Storages/StorageHDFS.h index 73342cf3671..44f0286f97e 100644 --- a/dbms/src/Storages/StorageHDFS.h +++ b/dbms/src/Storages/StorageHDFS.h @@ -16,15 +16,9 @@ namespace DB class StorageHDFS : public ext::shared_ptr_helper, public IStorage { public: - String getName() const override - { - return "HDFS"; - } - - String getTableName() const override - { - return table_name; - } + String getName() const override { return "HDFS"; } + String getTableName() const override { return table_name; } + String getDatabaseName() const override { return database_name; } BlockInputStreams read(const Names & column_names, const SelectQueryInfo & query_info, @@ -39,6 +33,7 @@ public: protected: StorageHDFS(const String & uri_, + const String & database_name_, const String & table_name_, const String & format_name_, const ColumnsDescription & columns_, @@ -48,6 +43,7 @@ private: String uri; String format_name; String table_name; + String database_name; Context & context; Logger * log = &Logger::get("StorageHDFS"); diff --git a/dbms/src/Storages/StorageJoin.cpp b/dbms/src/Storages/StorageJoin.cpp index 1c9cca0dc21..8a38c6fa8ff 100644 --- a/dbms/src/Storages/StorageJoin.cpp +++ b/dbms/src/Storages/StorageJoin.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include /// toLower #include @@ -24,10 +25,10 @@ namespace ErrorCodes extern const int BAD_ARGUMENTS; } - StorageJoin::StorageJoin( const String & path_, - const String & name_, + const String & database_name_, + const String & table_name_, const Names & key_names_, bool use_nulls_, SizeLimits limits_, @@ -35,7 +36,7 @@ StorageJoin::StorageJoin( ASTTableJoin::Strictness strictness_, const ColumnsDescription & columns_, bool overwrite) - : StorageSetOrJoinBase{path_, name_, columns_} + : StorageSetOrJoinBase{path_, database_name_, table_name_, columns_} , key_names(key_names_) , use_nulls(use_nulls_) , limits(limits_) @@ -160,6 +161,7 @@ void registerStorageJoin(StorageFactory & factory) return StorageJoin::create( args.data_path, + args.database_name, args.table_name, key_names, join_use_nulls.value, @@ -230,9 +232,8 @@ protected: return Block(); Block block; - if (parent.dispatch([&](auto, auto strictness, auto & map) { block = createBlock(map); })) - ; - else + if (!joinDispatch(parent.kind, parent.strictness, parent.maps, + [&](auto, auto strictness, auto & map) { block = createBlock(map); })) throw Exception("Logical error: unknown JOIN strictness (must be ANY or ALL)", ErrorCodes::LOGICAL_ERROR); return block; } diff --git a/dbms/src/Storages/StorageJoin.h b/dbms/src/Storages/StorageJoin.h index 3f5341d2822..356f4b0e7d9 100644 --- a/dbms/src/Storages/StorageJoin.h +++ b/dbms/src/Storages/StorageJoin.h @@ -57,7 +57,8 @@ private: protected: StorageJoin( const String & path_, - const String & name_, + const String & database_name_, + const String & table_name_, const Names & key_names_, bool use_nulls_, SizeLimits limits_, diff --git a/dbms/src/Storages/StorageLog.cpp b/dbms/src/Storages/StorageLog.cpp index afef7af57e9..12e45ca96bc 100644 --- a/dbms/src/Storages/StorageLog.cpp +++ b/dbms/src/Storages/StorageLog.cpp @@ -211,7 +211,7 @@ Block LogBlockInputStream::readImpl() } catch (Exception & e) { - e.addMessage("while reading column " + name_type.name + " at " + storage.path + escapeForFileName(storage.name)); + e.addMessage("while reading column " + name_type.name + " at " + storage.path + escapeForFileName(storage.table_name)); throw; } @@ -419,24 +419,25 @@ void LogBlockOutputStream::writeMarks(MarksForColumns && marks) StorageLog::StorageLog( const std::string & path_, - const std::string & name_, + const std::string & database_name_, + const std::string & table_name_, const ColumnsDescription & columns_, size_t max_compress_block_size_) : IStorage{columns_}, - path(path_), name(name_), + path(path_), table_name(table_name_), database_name(database_name_), max_compress_block_size(max_compress_block_size_), - file_checker(path + escapeForFileName(name) + '/' + "sizes.json") + file_checker(path + escapeForFileName(table_name) + '/' + "sizes.json") { if (path.empty()) throw Exception("Storage " + getName() + " requires data path", ErrorCodes::INCORRECT_FILE_NAME); /// create files if they do not exist - Poco::File(path + escapeForFileName(name) + '/').createDirectories(); + Poco::File(path + escapeForFileName(table_name) + '/').createDirectories(); for (const auto & column : getColumns().getAllPhysical()) addFiles(column.name, *column.type); - marks_file = Poco::File(path + escapeForFileName(name) + '/' + DBMS_STORAGE_LOG_MARKS_FILE_NAME); + marks_file = Poco::File(path + escapeForFileName(table_name) + '/' + DBMS_STORAGE_LOG_MARKS_FILE_NAME); } @@ -455,7 +456,7 @@ void StorageLog::addFiles(const String & column_name, const IDataType & type) ColumnData & column_data = files[stream_name]; column_data.column_index = file_count; column_data.data_file = Poco::File{ - path + escapeForFileName(name) + '/' + stream_name + DBMS_STORAGE_LOG_DATA_FILE_EXTENSION}; + path + escapeForFileName(table_name) + '/' + stream_name + DBMS_STORAGE_LOG_DATA_FILE_EXTENSION}; column_names_by_idx.push_back(stream_name); ++file_count; @@ -508,28 +509,29 @@ void StorageLog::loadMarks() } -void StorageLog::rename(const String & new_path_to_db, const String & /*new_database_name*/, const String & new_table_name) +void StorageLog::rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) { std::unique_lock lock(rwlock); /// Rename directory with data. - Poco::File(path + escapeForFileName(name)).renameTo(new_path_to_db + escapeForFileName(new_table_name)); + Poco::File(path + escapeForFileName(table_name)).renameTo(new_path_to_db + escapeForFileName(new_table_name)); path = new_path_to_db; - name = new_table_name; - file_checker.setPath(path + escapeForFileName(name) + '/' + "sizes.json"); + table_name = new_table_name; + database_name = new_database_name; + file_checker.setPath(path + escapeForFileName(table_name) + '/' + "sizes.json"); for (auto & file : files) - file.second.data_file = Poco::File(path + escapeForFileName(name) + '/' + Poco::Path(file.second.data_file.path()).getFileName()); + file.second.data_file = Poco::File(path + escapeForFileName(table_name) + '/' + Poco::Path(file.second.data_file.path()).getFileName()); - marks_file = Poco::File(path + escapeForFileName(name) + '/' + DBMS_STORAGE_LOG_MARKS_FILE_NAME); + marks_file = Poco::File(path + escapeForFileName(table_name) + '/' + DBMS_STORAGE_LOG_MARKS_FILE_NAME); } void StorageLog::truncate(const ASTPtr &, const Context &) { std::shared_lock lock(rwlock); - String table_dir = path + escapeForFileName(name); + String table_dir = path + escapeForFileName(table_name); files.clear(); file_count = 0; @@ -625,7 +627,7 @@ BlockOutputStreamPtr StorageLog::write( return std::make_shared(*this); } -bool StorageLog::checkData() const +CheckResults StorageLog::checkData(const ASTPtr & /* query */, const Context & /* context */) { std::shared_lock lock(rwlock); return file_checker.check(); @@ -642,7 +644,7 @@ void registerStorageLog(StorageFactory & factory) ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); return StorageLog::create( - args.data_path, args.table_name, args.columns, + args.data_path, args.database_name, args.table_name, args.columns, args.context.getSettings().max_compress_block_size); }); } diff --git a/dbms/src/Storages/StorageLog.h b/dbms/src/Storages/StorageLog.h index cf0d07a3bfe..f612d0ab29a 100644 --- a/dbms/src/Storages/StorageLog.h +++ b/dbms/src/Storages/StorageLog.h @@ -24,7 +24,8 @@ friend class LogBlockOutputStream; public: std::string getName() const override { return "Log"; } - std::string getTableName() const override { return name; } + std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } BlockInputStreams read( const Names & column_names, @@ -38,11 +39,11 @@ public: void rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) override; - bool checkData() const override; + CheckResults checkData(const ASTPtr & /* query */, const Context & /* context */) override; void truncate(const ASTPtr &, const Context &) override; - std::string full_path() const { return path + escapeForFileName(name) + '/';} + std::string full_path() const { return path + escapeForFileName(table_name) + '/';} String getDataPath() const override { return full_path(); } @@ -53,13 +54,15 @@ protected: */ StorageLog( const std::string & path_, - const std::string & name_, + const std::string & database_name_, + const std::string & table_name_, const ColumnsDescription & columns_, size_t max_compress_block_size_); private: String path; - String name; + String table_name; + String database_name; mutable std::shared_mutex rwlock; @@ -119,7 +122,7 @@ private: */ const Marks & getMarksWithRealRowCount() const; - std::string getFullPath() const { return path + escapeForFileName(name) + '/'; } + std::string getFullPath() const { return path + escapeForFileName(table_name) + '/'; } }; } diff --git a/dbms/src/Storages/StorageMaterializedView.cpp b/dbms/src/Storages/StorageMaterializedView.cpp index c843312e3d7..8a33e8af030 100644 --- a/dbms/src/Storages/StorageMaterializedView.cpp +++ b/dbms/src/Storages/StorageMaterializedView.cpp @@ -297,7 +297,7 @@ static void executeRenameQuery(Context & global_context, const String & database } -void StorageMaterializedView::rename(const String & /*new_path_to_db*/, const String & /*new_database_name*/, const String & new_table_name) +void StorageMaterializedView::rename(const String & /*new_path_to_db*/, const String & new_database_name, const String & new_table_name) { if (has_inner_table && tryGetTargetTable()) { @@ -313,6 +313,7 @@ void StorageMaterializedView::rename(const String & /*new_path_to_db*/, const St DatabaseAndTableName(database_name, table_name)); table_name = new_table_name; + database_name = new_database_name; global_context.addDependencyUnsafe( DatabaseAndTableName(select_database_name, select_table_name), diff --git a/dbms/src/Storages/StorageMaterializedView.h b/dbms/src/Storages/StorageMaterializedView.h index 5b14b90d77b..452ee7d51c0 100644 --- a/dbms/src/Storages/StorageMaterializedView.h +++ b/dbms/src/Storages/StorageMaterializedView.h @@ -14,6 +14,8 @@ class StorageMaterializedView : public ext::shared_ptr_helperclone(); } NameAndTypePair getColumn(const String & column_name) const override; diff --git a/dbms/src/Storages/StorageMemory.cpp b/dbms/src/Storages/StorageMemory.cpp index ddcf649a726..5e8f100f2f6 100644 --- a/dbms/src/Storages/StorageMemory.cpp +++ b/dbms/src/Storages/StorageMemory.cpp @@ -74,8 +74,8 @@ private: }; -StorageMemory::StorageMemory(String table_name_, ColumnsDescription columns_description_) - : IStorage{std::move(columns_description_)}, table_name(std::move(table_name_)) +StorageMemory::StorageMemory(String database_name_, String table_name_, ColumnsDescription columns_description_) + : IStorage{std::move(columns_description_)}, database_name(std::move(database_name_)), table_name(std::move(table_name_)) { } @@ -143,7 +143,7 @@ void registerStorageMemory(StorageFactory & factory) "Engine " + args.engine_name + " doesn't support any arguments (" + toString(args.engine_args.size()) + " given)", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); - return StorageMemory::create(args.table_name, args.columns); + return StorageMemory::create(args.database_name, args.table_name, args.columns); }); } diff --git a/dbms/src/Storages/StorageMemory.h b/dbms/src/Storages/StorageMemory.h index 89947b50b8f..e4a0f0cf9d4 100644 --- a/dbms/src/Storages/StorageMemory.h +++ b/dbms/src/Storages/StorageMemory.h @@ -23,8 +23,9 @@ friend class MemoryBlockInputStream; friend class MemoryBlockOutputStream; public: - std::string getName() const override { return "Memory"; } - std::string getTableName() const override { return table_name; } + String getName() const override { return "Memory"; } + String getTableName() const override { return table_name; } + String getDatabaseName() const override { return database_name; } size_t getSize() const { return data.size(); } @@ -42,9 +43,10 @@ public: void truncate(const ASTPtr &, const Context &) override; - void rename(const String & /*new_path_to_db*/, const String & /*new_database_name*/, const String & new_table_name) override { table_name = new_table_name; } + void rename(const String & /*new_path_to_db*/, const String & new_database_name, const String & new_table_name) override { table_name = new_table_name; database_name = new_database_name; } private: + String database_name; String table_name; /// The data itself. `list` - so that when inserted to the end, the existing iterators are not invalidated. @@ -53,7 +55,7 @@ private: std::mutex mutex; protected: - StorageMemory(String table_name_, ColumnsDescription columns_description_); + StorageMemory(String database_name_, String table_name_, ColumnsDescription columns_description_); }; } diff --git a/dbms/src/Storages/StorageMerge.cpp b/dbms/src/Storages/StorageMerge.cpp index 645ec1e9230..4c029fab677 100644 --- a/dbms/src/Storages/StorageMerge.cpp +++ b/dbms/src/Storages/StorageMerge.cpp @@ -46,14 +46,18 @@ namespace ErrorCodes StorageMerge::StorageMerge( - const std::string & name_, + const std::string & database_name_, + const std::string & table_name_, const ColumnsDescription & columns_, const String & source_database_, const String & table_name_regexp_, const Context & context_) - : IStorage{columns_}, - name(name_), source_database(source_database_), - table_name_regexp(table_name_regexp_), global_context(context_) + : IStorage(columns_, ColumnsDescription({{"_table", std::make_shared()}}, true)) + , table_name(table_name_) + , database_name(database_name_) + , source_database(source_database_) + , table_name_regexp(table_name_regexp_) + , global_context(context_) { } @@ -61,44 +65,29 @@ StorageMerge::StorageMerge( /// NOTE: structure of underlying tables as well as their set are not constant, /// so the results of these methods may become obsolete after the call. -bool StorageMerge::isVirtualColumn(const String & column_name) const -{ - if (column_name != "_table") - return false; - - return !IStorage::hasColumn(column_name); -} - NameAndTypePair StorageMerge::getColumn(const String & column_name) const { - if (IStorage::hasColumn(column_name)) - return IStorage::getColumn(column_name); + if (!IStorage::hasColumn(column_name)) + { + auto first_table = getFirstTable([](auto &&) { return true; }); + if (first_table) + return first_table->getColumn(column_name); + } - /// virtual column of the Merge table itself - if (column_name == "_table") - return { column_name, std::make_shared() }; - - /// virtual (and real) columns of the underlying tables - auto first_table = getFirstTable([](auto &&) { return true; }); - if (first_table) - return first_table->getColumn(column_name); - - throw Exception("There is no column " + column_name + " in table.", ErrorCodes::NO_SUCH_COLUMN_IN_TABLE); + return IStorage::getColumn(column_name); } + bool StorageMerge::hasColumn(const String & column_name) const { - if (column_name == "_table") - return true; + if (!IStorage::hasColumn(column_name)) + { + auto first_table = getFirstTable([](auto &&) { return true; }); + if (first_table) + return first_table->hasColumn(column_name); + } - if (IStorage::hasColumn(column_name)) - return true; - - auto first_table = getFirstTable([](auto &&) { return true; }); - if (first_table) - return first_table->hasColumn(column_name); - - return false; + return true; } @@ -178,7 +167,7 @@ BlockInputStreams StorageMerge::read( const Context & context, QueryProcessingStage::Enum processed_stage, const size_t max_block_size, - const unsigned num_streams) + unsigned num_streams) { BlockInputStreams res; @@ -188,7 +177,7 @@ BlockInputStreams StorageMerge::read( for (const auto & column_name : column_names) { - if (isVirtualColumn(column_name)) + if (column_name == "_table" && isVirtualColumn(column_name)) has_table_virtual_column = true; else real_column_names.push_back(column_name); @@ -214,8 +203,10 @@ BlockInputStreams StorageMerge::read( return createSourceStreams( query_info, processed_stage, max_block_size, header, {}, {}, real_column_names, modified_context, 0, has_table_virtual_column); - size_t remaining_streams = num_streams; size_t tables_count = selected_tables.size(); + Float64 num_streams_multiplier = std::min(unsigned(tables_count), std::max(1U, unsigned(context.getSettingsRef().max_streams_multiplier_for_merge_tables))); + num_streams *= num_streams_multiplier; + size_t remaining_streams = num_streams; for (auto it = selected_tables.begin(); it != selected_tables.end(); ++it) { @@ -397,13 +388,13 @@ StorageMerge::StorageListWithLocks StorageMerge::getSelectedTables(const ASTPtr DatabaseIteratorPtr StorageMerge::getDatabaseIterator(const Context & context) const { auto database = context.getDatabase(source_database); - auto table_name_match = [this](const String & table_name) { return table_name_regexp.match(table_name); }; + auto table_name_match = [this](const String & table_name_) { return table_name_regexp.match(table_name_); }; return database->getIterator(global_context, table_name_match); } void StorageMerge::alter( - const AlterCommands & params, const String & database_name, const String & table_name, + const AlterCommands & params, const String & database_name_, const String & table_name_, const Context & context, TableStructureWriteLockHolder & table_lock_holder) { lockStructureExclusively(table_lock_holder, context.getCurrentQueryId()); @@ -411,7 +402,7 @@ void StorageMerge::alter( auto new_columns = getColumns(); auto new_indices = getIndices(); params.apply(new_columns); - context.getDatabase(database_name)->alterTable(context, table_name, new_columns, new_indices, {}); + context.getDatabase(database_name_)->alterTable(context, table_name_, new_columns, new_indices, {}); setColumns(new_columns); } @@ -502,7 +493,7 @@ void registerStorageMerge(StorageFactory & factory) String table_name_regexp = engine_args[1]->as().value.safeGet(); return StorageMerge::create( - args.table_name, args.columns, + args.database_name, args.table_name, args.columns, source_database, table_name_regexp, args.context); }); } diff --git a/dbms/src/Storages/StorageMerge.h b/dbms/src/Storages/StorageMerge.h index b5ebf97ba9d..6d02ad029cc 100644 --- a/dbms/src/Storages/StorageMerge.h +++ b/dbms/src/Storages/StorageMerge.h @@ -16,7 +16,8 @@ class StorageMerge : public ext::shared_ptr_helper, public IStorag { public: std::string getName() const override { return "Merge"; } - std::string getTableName() const override { return name; } + std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } bool isRemote() const override; @@ -26,6 +27,7 @@ public: bool supportsFinal() const override { return true; } bool supportsIndexForIn() const override { return true; } + /// Consider columns coming from the underlying tables NameAndTypePair getColumn(const String & column_name) const override; bool hasColumn(const String & column_name) const override; @@ -40,7 +42,7 @@ public: unsigned num_streams) override; void drop() override {} - void rename(const String & /*new_path_to_db*/, const String & /*new_database_name*/, const String & new_table_name) override { name = new_table_name; } + void rename(const String & /*new_path_to_db*/, const String & new_database_name, const String & new_table_name) override { table_name = new_table_name; database_name = new_database_name; } /// you need to add and remove columns in the sub-tables manually /// the structure of sub-tables is not checked @@ -51,7 +53,8 @@ public: bool mayBenefitFromIndexForIn(const ASTPtr & left_in_operand, const Context & query_context) const override; private: - String name; + String table_name; + String database_name; String source_database; OptimizedRegularExpression table_name_regexp; Context global_context; @@ -69,7 +72,8 @@ private: protected: StorageMerge( - const std::string & name_, + const std::string & database_name_, + const std::string & table_name_, const ColumnsDescription & columns_, const String & source_database_, const String & table_name_regexp_, @@ -86,8 +90,6 @@ protected: void convertingSourceStream(const Block & header, const Context & context, ASTPtr & query, BlockInputStreamPtr & source_stream, QueryProcessingStage::Enum processed_stage); - - bool isVirtualColumn(const String & column_name) const override; }; } diff --git a/dbms/src/Storages/StorageMergeTree.cpp b/dbms/src/Storages/StorageMergeTree.cpp index 87526e3f39d..d021866487c 100644 --- a/dbms/src/Storages/StorageMergeTree.cpp +++ b/dbms/src/Storages/StorageMergeTree.cpp @@ -7,8 +7,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -17,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -174,7 +177,7 @@ void StorageMergeTree::truncate(const ASTPtr &, const Context &) clearOldPartsFromFilesystem(); } -void StorageMergeTree::rename(const String & new_path_to_db, const String & /*new_database_name*/, const String & new_table_name) +void StorageMergeTree::rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) { std::string new_full_path = new_path_to_db + escapeForFileName(new_table_name) + '/'; @@ -182,6 +185,7 @@ void StorageMergeTree::rename(const String & new_path_to_db, const String & /*ne path = new_path_to_db; table_name = new_table_name; + database_name = new_database_name; full_path = new_full_path; /// NOTE: Logger names are not updated. @@ -1057,6 +1061,11 @@ void StorageMergeTree::replacePartitionFrom(const StoragePtr & source_table, con for (const DataPartPtr & src_part : src_parts) { + if (!canReplacePartition(src_part)) + throw Exception( + "Cannot replace partition '" + partition_id + "' because part '" + src_part->name + "' has inconsistent granularity with table", + ErrorCodes::LOGICAL_ERROR); + /// This will generate unique name in scope of current server process. Int64 temp_index = insert_increment.get(); MergeTreePartInfo dst_part_info(partition_id, temp_index, temp_index, src_part->info.level); @@ -1116,4 +1125,59 @@ ActionLock StorageMergeTree::getActionLock(StorageActionBlockType action_type) return {}; } +CheckResults StorageMergeTree::checkData(const ASTPtr & query, const Context & context) +{ + CheckResults results; + DataPartsVector data_parts; + if (const auto & check_query = query->as(); check_query.partition) + { + String partition_id = getPartitionIDFromQuery(check_query.partition, context); + data_parts = getDataPartsVectorInPartition(MergeTreeDataPartState::Committed, partition_id); + } + else + data_parts = getDataPartsVector(); + + for (auto & part : data_parts) + { + String full_part_path = part->getFullPath(); + /// If the checksums file is not present, calculate the checksums and write them to disk. + String checksums_path = full_part_path + "checksums.txt"; + String tmp_checksums_path = full_part_path + "checksums.txt.tmp"; + if (!Poco::File(checksums_path).exists()) + { + try + { + auto calculated_checksums = checkDataPart(part, false, primary_key_data_types, skip_indices); + calculated_checksums.checkEqual(part->checksums, true); + WriteBufferFromFile out(tmp_checksums_path, 4096); + part->checksums.write(out); + Poco::File(tmp_checksums_path).renameTo(checksums_path); + results.emplace_back(part->name, true, "Checksums recounted and written to disk."); + } + catch (const Exception & ex) + { + Poco::File tmp_file(tmp_checksums_path); + if (tmp_file.exists()) + tmp_file.remove(); + + results.emplace_back(part->name, false, + "Check of part finished with error: '" + ex.message() + "'"); + } + } + else + { + try + { + checkDataPart(part, true, primary_key_data_types, skip_indices); + results.emplace_back(part->name, true, ""); + } + catch (const Exception & ex) + { + results.emplace_back(part->name, false, ex.message()); + } + } + } + return results; +} + } diff --git a/dbms/src/Storages/StorageMergeTree.h b/dbms/src/Storages/StorageMergeTree.h index b5156ce7137..0de9618d915 100644 --- a/dbms/src/Storages/StorageMergeTree.h +++ b/dbms/src/Storages/StorageMergeTree.h @@ -70,6 +70,8 @@ public: String getDataPath() const override { return full_path; } + CheckResults checkData(const ASTPtr & query, const Context & context) override; + private: String path; diff --git a/dbms/src/Storages/StorageMySQL.cpp b/dbms/src/Storages/StorageMySQL.cpp index 37eaa5e7cd2..25a06a8bd4e 100644 --- a/dbms/src/Storages/StorageMySQL.cpp +++ b/dbms/src/Storages/StorageMySQL.cpp @@ -36,7 +36,9 @@ String backQuoteMySQL(const String & x) return res; } -StorageMySQL::StorageMySQL(const std::string & name, +StorageMySQL::StorageMySQL( + const std::string & database_name_, + const std::string & table_name_, mysqlxx::Pool && pool, const std::string & remote_database_name, const std::string & remote_table_name, @@ -45,7 +47,8 @@ StorageMySQL::StorageMySQL(const std::string & name, const ColumnsDescription & columns_, const Context & context) : IStorage{columns_} - , name(name) + , table_name(table_name_) + , database_name(database_name_) , remote_database_name(remote_database_name) , remote_table_name(remote_table_name) , replace_query{replace_query} @@ -230,6 +233,7 @@ void registerStorageMySQL(StorageFactory & factory) ErrorCodes::BAD_ARGUMENTS); return StorageMySQL::create( + args.database_name, args.table_name, std::move(pool), remote_database, diff --git a/dbms/src/Storages/StorageMySQL.h b/dbms/src/Storages/StorageMySQL.h index 312fca75c9e..f28bb2aaa55 100644 --- a/dbms/src/Storages/StorageMySQL.h +++ b/dbms/src/Storages/StorageMySQL.h @@ -20,7 +20,8 @@ class StorageMySQL : public ext::shared_ptr_helper, public IStorag { public: StorageMySQL( - const std::string & name, + const std::string & database_name_, + const std::string & table_name_, mysqlxx::Pool && pool, const std::string & remote_database_name, const std::string & remote_table_name, @@ -30,7 +31,8 @@ public: const Context & context); std::string getName() const override { return "MySQL"; } - std::string getTableName() const override { return name; } + std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } BlockInputStreams read( const Names & column_names, @@ -44,7 +46,8 @@ public: private: friend class StorageMySQLBlockOutputStream; - std::string name; + std::string table_name; + std::string database_name; std::string remote_database_name; std::string remote_table_name; diff --git a/dbms/src/Storages/StorageNull.cpp b/dbms/src/Storages/StorageNull.cpp index 1762c8372f5..f6de6e87e37 100644 --- a/dbms/src/Storages/StorageNull.cpp +++ b/dbms/src/Storages/StorageNull.cpp @@ -26,7 +26,7 @@ void registerStorageNull(StorageFactory & factory) "Engine " + args.engine_name + " doesn't support any arguments (" + toString(args.engine_args.size()) + " given)", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); - return StorageNull::create(args.table_name, args.columns); + return StorageNull::create(args.database_name, args.table_name, args.columns); }); } diff --git a/dbms/src/Storages/StorageNull.h b/dbms/src/Storages/StorageNull.h index 14ce1140680..fec7638706f 100644 --- a/dbms/src/Storages/StorageNull.h +++ b/dbms/src/Storages/StorageNull.h @@ -19,6 +19,7 @@ class StorageNull : public ext::shared_ptr_helper, public IStorage public: std::string getName() const override { return "Null"; } std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } BlockInputStreams read( const Names & column_names, @@ -36,9 +37,10 @@ public: return std::make_shared(getSampleBlock()); } - void rename(const String & /*new_path_to_db*/, const String & /*new_database_name*/, const String & new_table_name) override + void rename(const String & /*new_path_to_db*/, const String & new_database_name, const String & new_table_name) override { table_name = new_table_name; + database_name = new_database_name; } void alter( @@ -47,10 +49,11 @@ public: private: String table_name; + String database_name; protected: - StorageNull(String table_name_, ColumnsDescription columns_description_) - : IStorage{std::move(columns_description_)}, table_name(std::move(table_name_)) + StorageNull(String database_name_, String table_name_, ColumnsDescription columns_description_) + : IStorage{std::move(columns_description_)}, table_name(std::move(table_name_)), database_name(std::move(database_name_)) { } }; diff --git a/dbms/src/Storages/StorageReplicatedMergeTree.cpp b/dbms/src/Storages/StorageReplicatedMergeTree.cpp index 86298df3f19..b51da168192 100644 --- a/dbms/src/Storages/StorageReplicatedMergeTree.cpp +++ b/dbms/src/Storages/StorageReplicatedMergeTree.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -2380,7 +2381,7 @@ void StorageReplicatedMergeTree::removePartAndEnqueueFetch(const String & part_n auto results = zookeeper->multi(ops); - String path_created = dynamic_cast(*results[0]).path_created; + String path_created = dynamic_cast(*results.back()).path_created; log_entry->znode_name = path_created.substr(path_created.find_last_of('/') + 1); queue.insert(zookeeper, log_entry); } @@ -4784,6 +4785,12 @@ void StorageReplicatedMergeTree::replacePartitionFrom(const StoragePtr & source_ /// Save deduplication block ids with special prefix replace_partition auto & src_part = src_all_parts[i]; + + if (!canReplacePartition(src_part)) + throw Exception( + "Cannot replace partition '" + partition_id + "' because part '" + src_part->name + "' has inconsistent granularity with table", + ErrorCodes::LOGICAL_ERROR); + String hash_hex = src_part->checksums.getTotalChecksumHex(); String block_id_path = replace ? "" : (zookeeper_path + "/blocks/" + partition_id + "_replace_from_" + hash_hex); @@ -5101,4 +5108,31 @@ bool StorageReplicatedMergeTree::dropPartsInPartition( return true; } + +CheckResults StorageReplicatedMergeTree::checkData(const ASTPtr & query, const Context & context) +{ + CheckResults results; + DataPartsVector data_parts; + if (const auto & check_query = query->as(); check_query.partition) + { + String partition_id = getPartitionIDFromQuery(check_query.partition, context); + data_parts = getDataPartsVectorInPartition(MergeTreeDataPartState::Committed, partition_id); + } + else + data_parts = getDataPartsVector(); + + for (auto & part : data_parts) + { + try + { + results.push_back(part_check_thread.checkPart(part->name)); + } + catch (const Exception & ex) + { + results.emplace_back(part->name, false, "Check of part finished with error: '" + ex.message() + "'"); + } + } + return results; +} + } diff --git a/dbms/src/Storages/StorageReplicatedMergeTree.h b/dbms/src/Storages/StorageReplicatedMergeTree.h index eba0511e15e..59afb96a523 100644 --- a/dbms/src/Storages/StorageReplicatedMergeTree.h +++ b/dbms/src/Storages/StorageReplicatedMergeTree.h @@ -170,6 +170,8 @@ public: String getDataPath() const override { return full_path; } + CheckResults checkData(const ASTPtr & query, const Context & context) override; + private: /// Delete old parts from disk and from ZooKeeper. void clearOldPartsAndRemoveFromZK(); diff --git a/dbms/src/Storages/StorageSet.cpp b/dbms/src/Storages/StorageSet.cpp index f1f4f039c8c..0d649728096 100644 --- a/dbms/src/Storages/StorageSet.cpp +++ b/dbms/src/Storages/StorageSet.cpp @@ -88,9 +88,10 @@ BlockOutputStreamPtr StorageSetOrJoinBase::write(const ASTPtr & /*query*/, const StorageSetOrJoinBase::StorageSetOrJoinBase( const String & path_, + const String & database_name_, const String & table_name_, const ColumnsDescription & columns_) - : IStorage{columns_}, table_name(table_name_) + : IStorage{columns_}, table_name(table_name_), database_name(database_name_) { if (path_.empty()) throw Exception("Join and Set storages require data path", ErrorCodes::INCORRECT_FILE_NAME); @@ -102,9 +103,10 @@ StorageSetOrJoinBase::StorageSetOrJoinBase( StorageSet::StorageSet( const String & path_, - const String & name_, + const String & database_name_, + const String & table_name_, const ColumnsDescription & columns_) - : StorageSetOrJoinBase{path_, name_, columns_}, + : StorageSetOrJoinBase{path_, database_name_, table_name_, columns_}, set(std::make_shared(SizeLimits(), false)) { Block header = getSampleBlock(); @@ -186,7 +188,7 @@ void StorageSetOrJoinBase::restoreFromFile(const String & file_path) } -void StorageSetOrJoinBase::rename(const String & new_path_to_db, const String & /*new_database_name*/, const String & new_table_name) +void StorageSetOrJoinBase::rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) { /// Rename directory with data. String new_path = new_path_to_db + escapeForFileName(new_table_name); @@ -194,6 +196,7 @@ void StorageSetOrJoinBase::rename(const String & new_path_to_db, const String & path = new_path + "/"; table_name = new_table_name; + database_name = new_database_name; } @@ -206,7 +209,7 @@ void registerStorageSet(StorageFactory & factory) "Engine " + args.engine_name + " doesn't support any arguments (" + toString(args.engine_args.size()) + " given)", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); - return StorageSet::create(args.data_path, args.table_name, args.columns); + return StorageSet::create(args.data_path, args.database_name, args.table_name, args.columns); }); } diff --git a/dbms/src/Storages/StorageSet.h b/dbms/src/Storages/StorageSet.h index 0585dc271c6..1c2891b78e1 100644 --- a/dbms/src/Storages/StorageSet.h +++ b/dbms/src/Storages/StorageSet.h @@ -20,6 +20,7 @@ class StorageSetOrJoinBase : public IStorage public: String getTableName() const override { return table_name; } + String getDatabaseName() const override { return database_name; } void rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) override; @@ -30,11 +31,13 @@ public: protected: StorageSetOrJoinBase( const String & path_, + const String & database_name_, const String & table_name_, const ColumnsDescription & columns_); String path; String table_name; + String database_name; std::atomic increment = 0; /// For the backup file names. @@ -76,7 +79,8 @@ private: protected: StorageSet( const String & path_, - const String & name_, + const String & database_name_, + const String & table_name_, const ColumnsDescription & columns_); }; diff --git a/dbms/src/Storages/StorageStripeLog.cpp b/dbms/src/Storages/StorageStripeLog.cpp index dba2e64a88f..3052962606d 100644 --- a/dbms/src/Storages/StorageStripeLog.cpp +++ b/dbms/src/Storages/StorageStripeLog.cpp @@ -195,20 +195,21 @@ private: StorageStripeLog::StorageStripeLog( const std::string & path_, - const std::string & name_, + const std::string & database_name_, + const std::string & table_name_, const ColumnsDescription & columns_, bool attach, size_t max_compress_block_size_) : IStorage{columns_}, - path(path_), name(name_), + path(path_), table_name(table_name_), database_name(database_name_), max_compress_block_size(max_compress_block_size_), - file_checker(path + escapeForFileName(name) + '/' + "sizes.json"), + file_checker(path + escapeForFileName(table_name) + '/' + "sizes.json"), log(&Logger::get("StorageStripeLog")) { if (path.empty()) throw Exception("Storage " + getName() + " requires data path", ErrorCodes::INCORRECT_FILE_NAME); - String full_path = path + escapeForFileName(name) + '/'; + String full_path = path + escapeForFileName(table_name) + '/'; if (!attach) { /// create files if they do not exist @@ -218,16 +219,17 @@ StorageStripeLog::StorageStripeLog( } -void StorageStripeLog::rename(const String & new_path_to_db, const String & /*new_database_name*/, const String & new_table_name) +void StorageStripeLog::rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) { std::unique_lock lock(rwlock); /// Rename directory with data. - Poco::File(path + escapeForFileName(name)).renameTo(new_path_to_db + escapeForFileName(new_table_name)); + Poco::File(path + escapeForFileName(table_name)).renameTo(new_path_to_db + escapeForFileName(new_table_name)); path = new_path_to_db; - name = new_table_name; - file_checker.setPath(path + escapeForFileName(name) + "/" + "sizes.json"); + table_name = new_table_name; + database_name = new_database_name; + file_checker.setPath(path + escapeForFileName(table_name) + "/" + "sizes.json"); } @@ -282,7 +284,7 @@ BlockOutputStreamPtr StorageStripeLog::write( } -bool StorageStripeLog::checkData() const +CheckResults StorageStripeLog::checkData(const ASTPtr & /* query */, const Context & /* context */) { std::shared_lock lock(rwlock); return file_checker.check(); @@ -290,16 +292,16 @@ bool StorageStripeLog::checkData() const void StorageStripeLog::truncate(const ASTPtr &, const Context &) { - if (name.empty()) + if (table_name.empty()) throw Exception("Logical error: table name is empty", ErrorCodes::LOGICAL_ERROR); std::shared_lock lock(rwlock); - auto file = Poco::File(path + escapeForFileName(name)); + auto file = Poco::File(path + escapeForFileName(table_name)); file.remove(true); file.createDirectories(); - file_checker = FileChecker{path + escapeForFileName(name) + '/' + "sizes.json"}; + file_checker = FileChecker{path + escapeForFileName(table_name) + '/' + "sizes.json"}; } @@ -313,7 +315,7 @@ void registerStorageStripeLog(StorageFactory & factory) ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); return StorageStripeLog::create( - args.data_path, args.table_name, args.columns, + args.data_path, args.database_name, args.table_name, args.columns, args.attach, args.context.getSettings().max_compress_block_size); }); } diff --git a/dbms/src/Storages/StorageStripeLog.h b/dbms/src/Storages/StorageStripeLog.h index 6489c82873e..6d528353dbf 100644 --- a/dbms/src/Storages/StorageStripeLog.h +++ b/dbms/src/Storages/StorageStripeLog.h @@ -26,7 +26,8 @@ friend class StripeLogBlockOutputStream; public: std::string getName() const override { return "StripeLog"; } - std::string getTableName() const override { return name; } + std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } BlockInputStreams read( const Names & column_names, @@ -40,7 +41,7 @@ public: void rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) override; - bool checkData() const override; + CheckResults checkData(const ASTPtr & /* query */, const Context & /* context */) override; /// Data of the file. struct ColumnData @@ -49,7 +50,7 @@ public: }; using Files_t = std::map; - std::string full_path() const { return path + escapeForFileName(name) + '/';} + std::string full_path() const { return path + escapeForFileName(table_name) + '/';} String getDataPath() const override { return full_path(); } @@ -57,7 +58,8 @@ public: private: String path; - String name; + String table_name; + String database_name; size_t max_compress_block_size; @@ -69,7 +71,8 @@ private: protected: StorageStripeLog( const std::string & path_, - const std::string & name_, + const std::string & database_name_, + const std::string & table_name_, const ColumnsDescription & columns_, bool attach, size_t max_compress_block_size_); diff --git a/dbms/src/Storages/StorageTinyLog.cpp b/dbms/src/Storages/StorageTinyLog.cpp index 4690ab925e8..24a75496a24 100644 --- a/dbms/src/Storages/StorageTinyLog.cpp +++ b/dbms/src/Storages/StorageTinyLog.cpp @@ -32,6 +32,7 @@ #include #include +#include #include @@ -320,20 +321,21 @@ void TinyLogBlockOutputStream::write(const Block & block) StorageTinyLog::StorageTinyLog( const std::string & path_, - const std::string & name_, + const std::string & database_name_, + const std::string & table_name_, const ColumnsDescription & columns_, bool attach, size_t max_compress_block_size_) : IStorage{columns_}, - path(path_), name(name_), + path(path_), table_name(table_name_), database_name(database_name_), max_compress_block_size(max_compress_block_size_), - file_checker(path + escapeForFileName(name) + '/' + "sizes.json"), + file_checker(path + escapeForFileName(table_name) + '/' + "sizes.json"), log(&Logger::get("StorageTinyLog")) { if (path.empty()) throw Exception("Storage " + getName() + " requires data path", ErrorCodes::INCORRECT_FILE_NAME); - String full_path = path + escapeForFileName(name) + '/'; + String full_path = path + escapeForFileName(table_name) + '/'; if (!attach) { /// create files if they do not exist @@ -360,7 +362,7 @@ void StorageTinyLog::addFiles(const String & column_name, const IDataType & type ColumnData column_data; files.insert(std::make_pair(stream_name, column_data)); files[stream_name].data_file = Poco::File( - path + escapeForFileName(name) + '/' + stream_name + DBMS_STORAGE_LOG_DATA_FILE_EXTENSION); + path + escapeForFileName(table_name) + '/' + stream_name + DBMS_STORAGE_LOG_DATA_FILE_EXTENSION); } }; @@ -369,17 +371,18 @@ void StorageTinyLog::addFiles(const String & column_name, const IDataType & type } -void StorageTinyLog::rename(const String & new_path_to_db, const String & /*new_database_name*/, const String & new_table_name) +void StorageTinyLog::rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) { /// Rename directory with data. - Poco::File(path + escapeForFileName(name)).renameTo(new_path_to_db + escapeForFileName(new_table_name)); + Poco::File(path + escapeForFileName(table_name)).renameTo(new_path_to_db + escapeForFileName(new_table_name)); path = new_path_to_db; - name = new_table_name; - file_checker.setPath(path + escapeForFileName(name) + "/" + "sizes.json"); + table_name = new_table_name; + database_name = new_database_name; + file_checker.setPath(path + escapeForFileName(table_name) + "/" + "sizes.json"); for (Files_t::iterator it = files.begin(); it != files.end(); ++it) - it->second.data_file = Poco::File(path + escapeForFileName(name) + '/' + Poco::Path(it->second.data_file.path()).getFileName()); + it->second.data_file = Poco::File(path + escapeForFileName(table_name) + '/' + Poco::Path(it->second.data_file.path()).getFileName()); } @@ -404,22 +407,22 @@ BlockOutputStreamPtr StorageTinyLog::write( } -bool StorageTinyLog::checkData() const +CheckResults StorageTinyLog::checkData(const ASTPtr & /* query */, const Context & /* context */) { return file_checker.check(); } void StorageTinyLog::truncate(const ASTPtr &, const Context &) { - if (name.empty()) + if (table_name.empty()) throw Exception("Logical error: table name is empty", ErrorCodes::LOGICAL_ERROR); - auto file = Poco::File(path + escapeForFileName(name)); + auto file = Poco::File(path + escapeForFileName(table_name)); file.remove(true); file.createDirectories(); files.clear(); - file_checker = FileChecker{path + escapeForFileName(name) + '/' + "sizes.json"}; + file_checker = FileChecker{path + escapeForFileName(table_name) + '/' + "sizes.json"}; for (const auto &column : getColumns().getAllPhysical()) addFiles(column.name, *column.type); @@ -436,7 +439,7 @@ void registerStorageTinyLog(StorageFactory & factory) ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); return StorageTinyLog::create( - args.data_path, args.table_name, args.columns, + args.data_path, args.database_name, args.table_name, args.columns, args.attach, args.context.getSettings().max_compress_block_size); }); } diff --git a/dbms/src/Storages/StorageTinyLog.h b/dbms/src/Storages/StorageTinyLog.h index 5b8e4bc90ac..7a360af632e 100644 --- a/dbms/src/Storages/StorageTinyLog.h +++ b/dbms/src/Storages/StorageTinyLog.h @@ -25,7 +25,8 @@ friend class TinyLogBlockOutputStream; public: std::string getName() const override { return "TinyLog"; } - std::string getTableName() const override { return name; } + std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } BlockInputStreams read( const Names & column_names, @@ -39,7 +40,7 @@ public: void rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) override; - bool checkData() const override; + CheckResults checkData(const ASTPtr & /* query */, const Context & /* context */) override; /// Column data struct ColumnData @@ -48,7 +49,7 @@ public: }; using Files_t = std::map; - std::string full_path() const { return path + escapeForFileName(name) + '/';} + std::string full_path() const { return path + escapeForFileName(table_name) + '/';} String getDataPath() const override { return full_path(); } @@ -56,7 +57,8 @@ public: private: String path; - String name; + String table_name; + String database_name; size_t max_compress_block_size; @@ -72,7 +74,8 @@ private: protected: StorageTinyLog( const std::string & path_, - const std::string & name_, + const std::string & database_name_, + const std::string & table_name_, const ColumnsDescription & columns_, bool attach, size_t max_compress_block_size_); diff --git a/dbms/src/Storages/StorageURL.cpp b/dbms/src/Storages/StorageURL.cpp index 7ebae3f66db..8a36c008be9 100644 --- a/dbms/src/Storages/StorageURL.cpp +++ b/dbms/src/Storages/StorageURL.cpp @@ -26,10 +26,11 @@ namespace ErrorCodes IStorageURLBase::IStorageURLBase(const Poco::URI & uri_, const Context & context_, + const std::string & database_name_, const std::string & table_name_, const String & format_name_, const ColumnsDescription & columns_) - : IStorage(columns_), uri(uri_), context_global(context_), format_name(format_name_), table_name(table_name_) + : IStorage(columns_), uri(uri_), context_global(context_), format_name(format_name_), table_name(table_name_), database_name(database_name_) { } @@ -182,7 +183,11 @@ BlockInputStreams IStorageURLBase::read(const Names & column_names, return {std::make_shared(block_input, column_defaults, context)}; } -void IStorageURLBase::rename(const String & /*new_path_to_db*/, const String & /*new_database_name*/, const String & /*new_table_name*/) {} +void IStorageURLBase::rename(const String & /*new_path_to_db*/, const String & new_database_name, const String & new_table_name) +{ + table_name = new_table_name; + database_name = new_database_name; +} BlockOutputStreamPtr IStorageURLBase::write(const ASTPtr & /*query*/, const Context & /*context*/) { @@ -209,7 +214,7 @@ void registerStorageURL(StorageFactory & factory) String format_name = engine_args[1]->as().value.safeGet(); - return StorageURL::create(uri, args.table_name, format_name, args.columns, args.context); + return StorageURL::create(uri, args.database_name, args.table_name, format_name, args.columns, args.context); }); } } diff --git a/dbms/src/Storages/StorageURL.h b/dbms/src/Storages/StorageURL.h index b84898c696d..361b0f6c35e 100644 --- a/dbms/src/Storages/StorageURL.h +++ b/dbms/src/Storages/StorageURL.h @@ -16,10 +16,8 @@ namespace DB class IStorageURLBase : public IStorage { public: - String getTableName() const override - { - return table_name; - } + String getTableName() const override { return table_name; } + String getDatabaseName() const override { return database_name; } BlockInputStreams read(const Names & column_names, const SelectQueryInfo & query_info, @@ -35,6 +33,7 @@ public: protected: IStorageURLBase(const Poco::URI & uri_, const Context & context_, + const std::string & database_name_, const std::string & table_name_, const String & format_name_, const ColumnsDescription & columns_); @@ -45,6 +44,7 @@ protected: private: String format_name; String table_name; + String database_name; virtual std::string getReadMethod() const; @@ -67,11 +67,12 @@ class StorageURL : public ext::shared_ptr_helper, public IStorageURL { public: StorageURL(const Poco::URI & uri_, + const std::string & database_name_, const std::string & table_name_, const String & format_name_, const ColumnsDescription & columns_, Context & context_) - : IStorageURLBase(uri_, context_, table_name_, format_name_, columns_) + : IStorageURLBase(uri_, context_, database_name_, table_name_, format_name_, columns_) { } diff --git a/dbms/src/Storages/StorageView.cpp b/dbms/src/Storages/StorageView.cpp index 09d54f40938..9d4855b586a 100644 --- a/dbms/src/Storages/StorageView.cpp +++ b/dbms/src/Storages/StorageView.cpp @@ -27,10 +27,11 @@ namespace ErrorCodes StorageView::StorageView( + const String & database_name_, const String & table_name_, const ASTCreateQuery & query, const ColumnsDescription & columns_) - : IStorage{columns_}, table_name(table_name_) + : IStorage{columns_}, table_name(table_name_), database_name(database_name_) { if (!query.select) throw Exception("SELECT query is not specified for " + getName(), ErrorCodes::INCORRECT_QUERY); @@ -101,7 +102,7 @@ void registerStorageView(StorageFactory & factory) if (args.query.storage) throw Exception("Specifying ENGINE is not allowed for a View", ErrorCodes::INCORRECT_QUERY); - return StorageView::create(args.table_name, args.query, args.columns); + return StorageView::create(args.database_name, args.table_name, args.query, args.columns); }); } diff --git a/dbms/src/Storages/StorageView.h b/dbms/src/Storages/StorageView.h index afd9b5ce326..cda128027c2 100644 --- a/dbms/src/Storages/StorageView.h +++ b/dbms/src/Storages/StorageView.h @@ -15,6 +15,7 @@ class StorageView : public ext::shared_ptr_helper, public IStorage public: std::string getName() const override { return "View"; } std::string getTableName() const override { return table_name; } + std::string getDatabaseName() const override { return database_name; } /// It is passed inside the query and solved at its level. bool supportsSampling() const override { return true; } @@ -28,19 +29,22 @@ public: size_t max_block_size, unsigned num_streams) override; - void rename(const String & /*new_path_to_db*/, const String & /*new_database_name*/, const String & new_table_name) override + void rename(const String & /*new_path_to_db*/, const String & new_database_name, const String & new_table_name) override { table_name = new_table_name; + database_name = new_database_name; } private: String table_name; + String database_name; ASTPtr inner_query; void replaceTableNameWithSubquery(ASTSelectQuery * select_query, ASTPtr & subquery); protected: StorageView( + const String & database_name_, const String & table_name_, const ASTCreateQuery & query, const ColumnsDescription & columns_); diff --git a/dbms/src/Storages/StorageXDBC.cpp b/dbms/src/Storages/StorageXDBC.cpp index 6e57f8a4286..57327fc4dcd 100644 --- a/dbms/src/Storages/StorageXDBC.cpp +++ b/dbms/src/Storages/StorageXDBC.cpp @@ -22,13 +22,15 @@ namespace ErrorCodes } -StorageXDBC::StorageXDBC(const std::string & table_name_, +StorageXDBC::StorageXDBC( + const std::string & database_name_, + const std::string & table_name_, const std::string & remote_database_name_, const std::string & remote_table_name_, const ColumnsDescription & columns_, const Context & context_, const BridgeHelperPtr bridge_helper_) - : IStorageURLBase(Poco::URI(), context_, table_name_, IXDBCBridgeHelper::DEFAULT_FORMAT, columns_) + : IStorageURLBase(Poco::URI(), context_, database_name_, table_name_, IXDBCBridgeHelper::DEFAULT_FORMAT, columns_) , bridge_helper(bridge_helper_) , remote_database_name(remote_database_name_) , remote_table_name(remote_table_name_) @@ -116,7 +118,7 @@ namespace BridgeHelperPtr bridge_helper = std::make_shared>(args.context, args.context.getSettingsRef().http_receive_timeout.value, engine_args[0]->as().value.safeGet()); - return std::make_shared(args.table_name, + return std::make_shared(args.database_name, args.table_name, engine_args[1]->as().value.safeGet(), engine_args[2]->as().value.safeGet(), args.columns, diff --git a/dbms/src/Storages/StorageXDBC.h b/dbms/src/Storages/StorageXDBC.h index 749e8910a24..23e108519b4 100644 --- a/dbms/src/Storages/StorageXDBC.h +++ b/dbms/src/Storages/StorageXDBC.h @@ -23,7 +23,8 @@ namespace DB unsigned num_streams) override; - StorageXDBC(const std::string & table_name_, + StorageXDBC(const std::string & database_name_, + const std::string & table_name_, const std::string & remote_database_name, const std::string & remote_table_name, const ColumnsDescription & columns_, diff --git a/dbms/src/Storages/System/CMakeLists.txt b/dbms/src/Storages/System/CMakeLists.txt index 8edfad534ec..18c452caf7b 100644 --- a/dbms/src/Storages/System/CMakeLists.txt +++ b/dbms/src/Storages/System/CMakeLists.txt @@ -12,7 +12,7 @@ include(${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake) add_headers_and_sources(storages_system .) list (APPEND storages_system_sources ${CONFIG_BUILD}) add_library(clickhouse_storages_system ${storages_system_headers} ${storages_system_sources}) -target_link_libraries(clickhouse_storages_system PRIVATE dbms common string_utils clickhouse_common_zookeeper) +target_link_libraries(clickhouse_storages_system PRIVATE dbms common string_utils clickhouse_common_zookeeper clickhouse_parsers) add_custom_target(generate-contributors ./StorageSystemContributors.sh SOURCES StorageSystemContributors.sh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} # BYPRODUCTS StorageSystemContributors.generated.cpp diff --git a/dbms/src/Storages/System/IStorageSystemOneBlock.h b/dbms/src/Storages/System/IStorageSystemOneBlock.h index 8cdbd1804dc..b5c8c2ad78f 100644 --- a/dbms/src/Storages/System/IStorageSystemOneBlock.h +++ b/dbms/src/Storages/System/IStorageSystemOneBlock.h @@ -25,10 +25,8 @@ public: setColumns(ColumnsDescription(Self::getNamesAndTypes())); } - std::string getTableName() const override - { - return name; - } + std::string getTableName() const override { return name; } + std::string getDatabaseName() const override { return "system"; } BlockInputStreams read(const Names & column_names, const SelectQueryInfo & query_info, diff --git a/dbms/src/Storages/System/StorageSystemBuildOptions.generated.cpp.in b/dbms/src/Storages/System/StorageSystemBuildOptions.generated.cpp.in index 99591648bae..63ddfe15649 100644 --- a/dbms/src/Storages/System/StorageSystemBuildOptions.generated.cpp.in +++ b/dbms/src/Storages/System/StorageSystemBuildOptions.generated.cpp.in @@ -40,6 +40,7 @@ const char * auto_config_build[] "USE_MIMALLOC", "@USE_MIMALLOC@", "USE_UNWIND", "@USE_UNWIND@", "USE_ICU", "@USE_ICU@", + "USE_H3", "@USE_H3@", "USE_MYSQL", "@USE_MYSQL@", "USE_RE2_ST", "@USE_RE2_ST@", "USE_VECTORCLASS", "@USE_VECTORCLASS@", diff --git a/dbms/src/Storages/System/StorageSystemClusters.cpp b/dbms/src/Storages/System/StorageSystemClusters.cpp index b33b2d86d0e..d9403aba688 100644 --- a/dbms/src/Storages/System/StorageSystemClusters.cpp +++ b/dbms/src/Storages/System/StorageSystemClusters.cpp @@ -10,7 +10,8 @@ namespace DB NamesAndTypesList StorageSystemClusters::getNamesAndTypes() { - return { + return + { {"cluster", std::make_shared()}, {"shard_num", std::make_shared()}, {"shard_weight", std::make_shared()}, @@ -48,7 +49,8 @@ void StorageSystemClusters::fillData(MutableColumns & res_columns, const Context res_columns[i++]->insert(shard_info.weight); res_columns[i++]->insert(replica_index + 1); res_columns[i++]->insert(address.host_name); - res_columns[i++]->insert(DNSResolver::instance().resolveHost(address.host_name).toString()); + auto resolved = address.getResolvedAddress(); + res_columns[i++]->insert(resolved ? resolved->host().toString() : String()); res_columns[i++]->insert(address.port); res_columns[i++]->insert(shard_info.isLocal()); res_columns[i++]->insert(address.user); diff --git a/dbms/src/Storages/System/StorageSystemColumns.h b/dbms/src/Storages/System/StorageSystemColumns.h index e1814c96ef1..b9aa04b0b25 100644 --- a/dbms/src/Storages/System/StorageSystemColumns.h +++ b/dbms/src/Storages/System/StorageSystemColumns.h @@ -15,8 +15,8 @@ class StorageSystemColumns : public ext::shared_ptr_helper { public: std::string getName() const override { return "SystemColumns"; } - std::string getTableName() const override { return name; } + std::string getDatabaseName() const override { return "system"; } BlockInputStreams read( const Names & column_names, diff --git a/dbms/src/Storages/System/StorageSystemContributors.generated.cpp b/dbms/src/Storages/System/StorageSystemContributors.generated.cpp index b81dea81f42..d05314c680d 100644 --- a/dbms/src/Storages/System/StorageSystemContributors.generated.cpp +++ b/dbms/src/Storages/System/StorageSystemContributors.generated.cpp @@ -1,4 +1,4 @@ -// autogenerated by dbms/src/Storages/System/StorageSystemContributors.sh +// autogenerated by ./StorageSystemContributors.sh const char * auto_contributors[] { "0xflotus", "821008736@qq.com", @@ -23,6 +23,7 @@ const char * auto_contributors[] { "Alexander Prudaev", "Alexander Sapin", "Alexander Tokmakov", + "Alexander Tretiakov", "Alexandr Krasheninnikov", "Alexandr Orlov", "Alexei Averchenko", @@ -147,6 +148,7 @@ const char * auto_contributors[] { "Konstantin Grabar", "Konstantin Lebedev", "Konstantin Podshumok", + "Korviakov Andrey", "Leonardo Cecchi", "Leopold Schabel", "Lev Borodin", @@ -175,6 +177,7 @@ const char * auto_contributors[] { "Maxim Khrisanfov", "Maxim Kuznetsov", "Maxim Nikulin", + "Maxim Sabyanin", "MaximAL", "MeiK", "Michael Furmur", @@ -198,6 +201,7 @@ const char * auto_contributors[] { "Neeke Gao", "Nicolae Vartolomei", "Nikhil Raman", + "Nikita Lapkov", "Nikita Vasilev", "Nikolai Kochetov", "Nikolay Kirsh", @@ -318,6 +322,7 @@ const char * auto_contributors[] { "chertus", "coraxster", "daoready", + "davydovska", "decaseal", "dmitry kuzmin", "eejoin", @@ -330,6 +335,7 @@ const char * auto_contributors[] { "filimonov", "flow", "foxxmary", + "fredchenbj", "ggerogery", "glockbender", "hcz", @@ -338,6 +344,7 @@ const char * auto_contributors[] { "igor.lapko", "ivan-kush", "ivanzhukov", + "javartisan", "javi", "javi santana", "kmeaw", @@ -380,17 +387,20 @@ const char * auto_contributors[] { "shangshujie", "shedx", "simon-says", + "spyros87", "stavrolia", "sundy-li", "sundyli", "svladykin", "tai", "topvisor", + "unknown", "urgordeadbeef", "velom", "vicdashkov", "zamulla", "zhang2014", + "Šimon Podlipský", "Георгий Кондратьев", "Дмитрий Канатников", "Иванов Евгений", diff --git a/dbms/src/Storages/System/StorageSystemDetachedParts.cpp b/dbms/src/Storages/System/StorageSystemDetachedParts.cpp index 088e14903df..9ae6f7b607a 100644 --- a/dbms/src/Storages/System/StorageSystemDetachedParts.cpp +++ b/dbms/src/Storages/System/StorageSystemDetachedParts.cpp @@ -23,6 +23,7 @@ class StorageSystemDetachedParts : public: std::string getName() const override { return "SystemDetachedParts"; } std::string getTableName() const override { return "detached_parts"; } + std::string getDatabaseName() const override { return "system"; } protected: explicit StorageSystemDetachedParts() diff --git a/dbms/src/Storages/System/StorageSystemNumbers.h b/dbms/src/Storages/System/StorageSystemNumbers.h index 99d9599dda2..452ec5a9ef5 100644 --- a/dbms/src/Storages/System/StorageSystemNumbers.h +++ b/dbms/src/Storages/System/StorageSystemNumbers.h @@ -25,6 +25,7 @@ class StorageSystemNumbers : public ext::shared_ptr_helper public: std::string getName() const override { return "SystemNumbers"; } std::string getTableName() const override { return name; } + std::string getDatabaseName() const override { return "system"; } BlockInputStreams read( const Names & column_names, diff --git a/dbms/src/Storages/System/StorageSystemOne.h b/dbms/src/Storages/System/StorageSystemOne.h index 721684b7802..974435e99f0 100644 --- a/dbms/src/Storages/System/StorageSystemOne.h +++ b/dbms/src/Storages/System/StorageSystemOne.h @@ -20,6 +20,7 @@ class StorageSystemOne : public ext::shared_ptr_helper, public public: std::string getName() const override { return "SystemOne"; } std::string getTableName() const override { return name; } + std::string getDatabaseName() const override { return "system"; } BlockInputStreams read( const Names & column_names, diff --git a/dbms/src/Storages/System/StorageSystemParts.cpp b/dbms/src/Storages/System/StorageSystemParts.cpp index 0240baf9604..ebcf36abfb7 100644 --- a/dbms/src/Storages/System/StorageSystemParts.cpp +++ b/dbms/src/Storages/System/StorageSystemParts.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace DB { @@ -45,6 +46,10 @@ StorageSystemParts::StorageSystemParts(const std::string & name) {"table", std::make_shared()}, {"engine", std::make_shared()}, {"path", std::make_shared()}, + + {"hash_of_all_files", std::make_shared()}, + {"hash_of_uncompressed_files", std::make_shared()}, + {"uncompressed_hash_of_compressed_files", std::make_shared()} } ) { @@ -107,6 +112,18 @@ void StorageSystemParts::processNextStorage(MutableColumns & columns, const Stor if (has_state_column) columns[i++]->insert(part->stateString()); + + MinimalisticDataPartChecksums helper; + helper.computeTotalChecksums(part->checksums); + + auto checksum = helper.hash_of_all_files; + columns[i++]->insert(getHexUIntLowercase(checksum.first) + getHexUIntLowercase(checksum.second)); + + checksum = helper.hash_of_uncompressed_files; + columns[i++]->insert(getHexUIntLowercase(checksum.first) + getHexUIntLowercase(checksum.second)); + + checksum = helper.uncompressed_hash_of_compressed_files; + columns[i++]->insert(getHexUIntLowercase(checksum.first) + getHexUIntLowercase(checksum.second)); } } diff --git a/dbms/src/Storages/System/StorageSystemPartsBase.cpp b/dbms/src/Storages/System/StorageSystemPartsBase.cpp index 05ae6e086e2..303a8ddd939 100644 --- a/dbms/src/Storages/System/StorageSystemPartsBase.cpp +++ b/dbms/src/Storages/System/StorageSystemPartsBase.cpp @@ -257,7 +257,7 @@ StorageSystemPartsBase::StorageSystemPartsBase(std::string name_, NamesAndTypesL auto add_alias = [&](const String & alias_name, const String & column_name) { - ColumnDescription column(alias_name, columns.get(column_name).type); + ColumnDescription column(alias_name, columns.get(column_name).type, false); column.default_desc.kind = ColumnDefaultKind::Alias; column.default_desc.expression = std::make_shared(column_name); columns.add(column); diff --git a/dbms/src/Storages/System/StorageSystemPartsBase.h b/dbms/src/Storages/System/StorageSystemPartsBase.h index da90d7524e7..080153a2a91 100644 --- a/dbms/src/Storages/System/StorageSystemPartsBase.h +++ b/dbms/src/Storages/System/StorageSystemPartsBase.h @@ -54,6 +54,7 @@ class StorageSystemPartsBase : public IStorage { public: std::string getTableName() const override { return name; } + std::string getDatabaseName() const override { return "system"; } NameAndTypePair getColumn(const String & column_name) const override; diff --git a/dbms/src/Storages/System/StorageSystemPartsColumns.cpp b/dbms/src/Storages/System/StorageSystemPartsColumns.cpp index 5d20e5797f4..6b8cb6ae836 100644 --- a/dbms/src/Storages/System/StorageSystemPartsColumns.cpp +++ b/dbms/src/Storages/System/StorageSystemPartsColumns.cpp @@ -46,13 +46,13 @@ StorageSystemPartsColumns::StorageSystemPartsColumns(const std::string & name) {"path", std::make_shared()}, {"column", std::make_shared()}, - {"type", std::make_shared() }, - {"default_kind", std::make_shared() }, - {"default_expression", std::make_shared() }, - {"column_bytes_on_disk", std::make_shared() }, - {"column_data_compressed_bytes", std::make_shared() }, - {"column_data_uncompressed_bytes", std::make_shared() }, - {"column_marks_bytes", std::make_shared() }, + {"type", std::make_shared()}, + {"default_kind", std::make_shared()}, + {"default_expression", std::make_shared()}, + {"column_bytes_on_disk", std::make_shared()}, + {"column_data_compressed_bytes", std::make_shared()}, + {"column_data_uncompressed_bytes", std::make_shared()}, + {"column_marks_bytes", std::make_shared()} } ) { @@ -100,6 +100,7 @@ void StorageSystemPartsColumns::processNextStorage(MutableColumns & columns, con using State = MergeTreeDataPart::State; for (const auto & column : part->columns) + { size_t j = 0; { diff --git a/dbms/src/Storages/System/StorageSystemReplicas.h b/dbms/src/Storages/System/StorageSystemReplicas.h index 53ba5ebd9bd..49865ad869a 100644 --- a/dbms/src/Storages/System/StorageSystemReplicas.h +++ b/dbms/src/Storages/System/StorageSystemReplicas.h @@ -17,6 +17,7 @@ class StorageSystemReplicas : public ext::shared_ptr_helper, public: std::string getName() const override { return "SystemTables"; } std::string getTableName() const override { return name; } + std::string getDatabaseName() const override { return "system"; } BlockInputStreams read( const Names & column_names, diff --git a/dbms/src/Storages/VirtualColumnUtils.cpp b/dbms/src/Storages/VirtualColumnUtils.cpp index 3ac32ce0f5b..cbb1feef3af 100644 --- a/dbms/src/Storages/VirtualColumnUtils.cpp +++ b/dbms/src/Storages/VirtualColumnUtils.cpp @@ -23,71 +23,11 @@ namespace DB { -namespace VirtualColumnUtils +namespace { -String chooseSuffix(const NamesAndTypesList & columns, const String & name) -{ - int id = 0; - String current_suffix; - while (true) - { - bool done = true; - for (const auto & it : columns) - if (it.name == name + current_suffix) - { - done = false; - break; - } - if (done) break; - ++id; - current_suffix = toString(id); - } - return current_suffix; -} - -String chooseSuffixForSet(const NamesAndTypesList & columns, const std::vector & names) -{ - int id = 0; - String current_suffix; - while (true) - { - bool done = true; - for (const auto & it : columns) - { - for (size_t i = 0; i < names.size(); ++i) - { - if (it.name == names[i] + current_suffix) - { - done = false; - break; - } - } - if (!done) - break; - } - if (done) - break; - ++id; - current_suffix = toString(id); - } - return current_suffix; -} - -void rewriteEntityInAst(ASTPtr ast, const String & column_name, const Field & value) -{ - auto & select = ast->as(); - if (!select.with()) - select.setExpression(ASTSelectQuery::Expression::WITH, std::make_shared()); - - auto literal = std::make_shared(value); - literal->alias = column_name; - literal->prefer_alias_to_column_name = true; - select.with()->children.push_back(literal); -} - /// Verifying that the function depends only on the specified columns -static bool isValidFunction(const ASTPtr & expression, const NameSet & columns) +bool isValidFunction(const ASTPtr & expression, const NameSet & columns) { for (size_t i = 0; i < expression->children.size(); ++i) if (!isValidFunction(expression->children[i], columns)) @@ -100,7 +40,7 @@ static bool isValidFunction(const ASTPtr & expression, const NameSet & columns) } /// Extract all subfunctions of the main conjunction, but depending only on the specified columns -static void extractFunctions(const ASTPtr & expression, const NameSet & columns, std::vector & result) +void extractFunctions(const ASTPtr & expression, const NameSet & columns, std::vector & result) { const auto * function = expression->as(); if (function && function->name == "and") @@ -115,7 +55,7 @@ static void extractFunctions(const ASTPtr & expression, const NameSet & columns, } /// Construct a conjunction from given functions -static ASTPtr buildWhereExpression(const ASTs & functions) +ASTPtr buildWhereExpression(const ASTs & functions) { if (functions.size() == 0) return nullptr; @@ -130,6 +70,23 @@ static ASTPtr buildWhereExpression(const ASTs & functions) return new_query; } +} + +namespace VirtualColumnUtils +{ + +void rewriteEntityInAst(ASTPtr ast, const String & column_name, const Field & value) +{ + auto & select = ast->as(); + if (!select.with()) + select.setExpression(ASTSelectQuery::Expression::WITH, std::make_shared()); + + auto literal = std::make_shared(value); + literal->alias = column_name; + literal->prefer_alias_to_column_name = true; + select.with()->children.push_back(literal); +} + void filterBlockWithQuery(const ASTPtr & query, Block & block, const Context & context) { const auto & select = query->as(); diff --git a/dbms/src/Storages/VirtualColumnUtils.h b/dbms/src/Storages/VirtualColumnUtils.h index a1e1db4f04c..4976deaa4c9 100644 --- a/dbms/src/Storages/VirtualColumnUtils.h +++ b/dbms/src/Storages/VirtualColumnUtils.h @@ -3,7 +3,7 @@ #include #include -#include +#include namespace DB @@ -16,13 +16,6 @@ class NamesAndTypesList; namespace VirtualColumnUtils { -/// Calculate the minimum numeric suffix to add to the string so that it is not present in the set -String chooseSuffix(const NamesAndTypesList & columns, const String & name); - -/// Calculate the minimum total numeric suffix to add to each string, -/// so that none is present in the set. -String chooseSuffixForSet(const NamesAndTypesList & columns, const std::vector & names); - /// Adds to the select query section `select column_name as value` /// For example select _port as 9000. void rewriteEntityInAst(ASTPtr ast, const String & column_name, const Field & value); @@ -33,14 +26,14 @@ void rewriteEntityInAst(ASTPtr ast, const String & column_name, const Field & va void filterBlockWithQuery(const ASTPtr & query, Block & block, const Context & context); /// Extract from the input stream a set of `name` column values -template -std::multiset extractSingleValueFromBlock(const Block & block, const String & name) +template +std::multiset extractSingleValueFromBlock(const Block & block, const String & name) { - std::multiset res; + std::multiset res; const ColumnWithTypeAndName & data = block.getByName(name); size_t rows = block.rows(); for (size_t i = 0; i < rows; ++i) - res.insert((*data.column)[i].get()); + res.insert((*data.column)[i].get()); return res; } diff --git a/dbms/src/Storages/tests/gtest_aux_funcs_for_adaptive_granularity.cpp b/dbms/src/Storages/tests/gtest_aux_funcs_for_adaptive_granularity.cpp index fc1166b18bb..95c56c74132 100644 --- a/dbms/src/Storages/tests/gtest_aux_funcs_for_adaptive_granularity.cpp +++ b/dbms/src/Storages/tests/gtest_aux_funcs_for_adaptive_granularity.cpp @@ -1,8 +1,3 @@ -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" -#pragma clang diagnostic ignored "-Wundef" -#endif #include #include #include @@ -30,14 +25,14 @@ TEST(AdaptiveIndexGranularity, FillGranularityToyTests) EXPECT_EQ(block1.bytes(), 80); { /// Granularity bytes are not set. Take default index_granularity. MergeTreeIndexGranularity index_granularity; - fillIndexGranularityImpl(block1, 0, 100, false, 0, index_granularity); + fillIndexGranularityImpl(block1, 0, 100, false, 0, index_granularity, false); EXPECT_EQ(index_granularity.getMarksCount(), 1); EXPECT_EQ(index_granularity.getMarkRows(0), 100); } { /// Granule size is less than block size. Block contains multiple granules. MergeTreeIndexGranularity index_granularity; - fillIndexGranularityImpl(block1, 16, 100, false, 0, index_granularity); + fillIndexGranularityImpl(block1, 16, 100, false, 0, index_granularity, true); EXPECT_EQ(index_granularity.getMarksCount(), 5); /// First granule with 8 rows, and second with 1 row for (size_t i = 0; i < index_granularity.getMarksCount(); ++i) EXPECT_EQ(index_granularity.getMarkRows(i), 2); @@ -46,7 +41,7 @@ TEST(AdaptiveIndexGranularity, FillGranularityToyTests) { /// Granule size is more than block size. Whole block (and maybe more) can be placed in single granule. MergeTreeIndexGranularity index_granularity; - fillIndexGranularityImpl(block1, 512, 100, false, 0, index_granularity); + fillIndexGranularityImpl(block1, 512, 100, false, 0, index_granularity, true); EXPECT_EQ(index_granularity.getMarksCount(), 1); for (size_t i = 0; i < index_granularity.getMarksCount(); ++i) EXPECT_EQ(index_granularity.getMarkRows(i), 64); @@ -55,7 +50,7 @@ TEST(AdaptiveIndexGranularity, FillGranularityToyTests) { /// Blocks with granule size MergeTreeIndexGranularity index_granularity; - fillIndexGranularityImpl(block1, 1, 100, true, 0, index_granularity); + fillIndexGranularityImpl(block1, 1, 100, true, 0, index_granularity, true); EXPECT_EQ(index_granularity.getMarksCount(), 1); for (size_t i = 0; i < index_granularity.getMarksCount(); ++i) EXPECT_EQ(index_granularity.getMarkRows(i), block1.rows()); @@ -63,7 +58,7 @@ TEST(AdaptiveIndexGranularity, FillGranularityToyTests) { /// Shift in index offset MergeTreeIndexGranularity index_granularity; - fillIndexGranularityImpl(block1, 16, 100, false, 6, index_granularity); + fillIndexGranularityImpl(block1, 16, 100, false, 6, index_granularity, true); EXPECT_EQ(index_granularity.getMarksCount(), 2); for (size_t i = 0; i < index_granularity.getMarksCount(); ++i) EXPECT_EQ(index_granularity.getMarkRows(i), 2); @@ -79,7 +74,7 @@ TEST(AdaptiveIndexGranularity, FillGranularitySequenceOfBlocks) auto block3 = getBlockWithSize(65536, 8); MergeTreeIndexGranularity index_granularity; for (const auto & block : {block1, block2, block3}) - fillIndexGranularityImpl(block, 1024, 8192, false, 0, index_granularity); + fillIndexGranularityImpl(block, 1024, 8192, false, 0, index_granularity, true); EXPECT_EQ(index_granularity.getMarksCount(), 192); /// granules for (size_t i = 0; i < index_granularity.getMarksCount(); ++i) @@ -92,7 +87,7 @@ TEST(AdaptiveIndexGranularity, FillGranularitySequenceOfBlocks) EXPECT_EQ(block1.rows() + block2.rows() + block3.rows(), 3136); MergeTreeIndexGranularity index_granularity; for (const auto & block : {block1, block2, block3}) - fillIndexGranularityImpl(block, 1024, 8192, false, 0, index_granularity); + fillIndexGranularityImpl(block, 1024, 8192, false, 0, index_granularity, true); EXPECT_EQ(index_granularity.getMarksCount(), 98); /// granules for (size_t i = 0; i < index_granularity.getMarksCount(); ++i) @@ -110,7 +105,7 @@ TEST(AdaptiveIndexGranularity, FillGranularitySequenceOfBlocks) size_t index_offset = 0; for (const auto & block : {block1, block2, block3}) { - fillIndexGranularityImpl(block, 16384, 8192, false, index_offset, index_granularity); + fillIndexGranularityImpl(block, 16384, 8192, false, index_offset, index_granularity, true); index_offset = index_granularity.getLastMarkRows() - block.rows(); } EXPECT_EQ(index_granularity.getMarksCount(), 1); /// granules diff --git a/dbms/src/Storages/tests/gtest_row_source_bits_test.cpp b/dbms/src/Storages/tests/gtest_row_source_bits_test.cpp index 7b2f25061b6..a6d9179c106 100644 --- a/dbms/src/Storages/tests/gtest_row_source_bits_test.cpp +++ b/dbms/src/Storages/tests/gtest_row_source_bits_test.cpp @@ -1,8 +1,3 @@ -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ - #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" - #pragma clang diagnostic ignored "-Wundef" -#endif #include #include diff --git a/dbms/src/Storages/tests/gtest_transform_query_for_external_database.cpp b/dbms/src/Storages/tests/gtest_transform_query_for_external_database.cpp index 4a25bff5d87..c17676bc655 100644 --- a/dbms/src/Storages/tests/gtest_transform_query_for_external_database.cpp +++ b/dbms/src/Storages/tests/gtest_transform_query_for_external_database.cpp @@ -1,8 +1,3 @@ -#pragma GCC diagnostic ignored "-Wsign-compare" -#ifdef __clang__ - #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" - #pragma clang diagnostic ignored "-Wundef" -#endif #include #include @@ -28,7 +23,8 @@ struct State { registerFunctions(); DatabasePtr database = std::make_shared("test"); - database->attachTable("table", StorageMemory::create("table", ColumnsDescription{columns})); + database->attachTable("table", StorageMemory::create("test", "table", ColumnsDescription{columns})); + context.makeGlobalContext(); context.addDatabase("test", database); context.setCurrentDatabase("test"); } @@ -54,22 +50,22 @@ void check(const std::string & query, const std::string & expected, const Contex TEST(TransformQueryForExternalDatabase, InWithSingleElement) { check("SELECT column FROM test.table WHERE 1 IN (1)", - "SELECT \"column\" FROM \"test\".\"table\" WHERE 1 IN (1)", + "SELECT \"column\" FROM \"test\".\"table\" WHERE 1 IN (1)", state().context, state().columns); check("SELECT column FROM test.table WHERE column IN (1, 2)", - "SELECT \"column\" FROM \"test\".\"table\" WHERE \"column\" IN (1, 2)", + "SELECT \"column\" FROM \"test\".\"table\" WHERE \"column\" IN (1, 2)", state().context, state().columns); check("SELECT column FROM test.table WHERE column NOT IN ('hello', 'world')", - "SELECT \"column\" FROM \"test\".\"table\" WHERE \"column\" NOT IN ('hello', 'world')", + "SELECT \"column\" FROM \"test\".\"table\" WHERE \"column\" NOT IN ('hello', 'world')", state().context, state().columns); } TEST(TransformQueryForExternalDatabase, Like) { check("SELECT column FROM test.table WHERE column LIKE '%hello%'", - "SELECT \"column\" FROM \"test\".\"table\" WHERE \"column\" LIKE '%hello%'", + "SELECT \"column\" FROM \"test\".\"table\" WHERE \"column\" LIKE '%hello%'", state().context, state().columns); check("SELECT column FROM test.table WHERE column NOT LIKE 'w%rld'", - "SELECT \"column\" FROM \"test\".\"table\" WHERE \"column\" NOT LIKE 'w%rld'", + "SELECT \"column\" FROM \"test\".\"table\" WHERE \"column\" NOT LIKE 'w%rld'", state().context, state().columns); } diff --git a/dbms/src/Storages/tests/storage_log.cpp b/dbms/src/Storages/tests/storage_log.cpp index db905731e6f..bcf7b1d4d03 100644 --- a/dbms/src/Storages/tests/storage_log.cpp +++ b/dbms/src/Storages/tests/storage_log.cpp @@ -25,10 +25,11 @@ try names_and_types.emplace_back("a", std::make_shared()); names_and_types.emplace_back("b", std::make_shared()); - StoragePtr table = StorageLog::create("./", "test", ColumnsDescription{names_and_types}, 1048576); + StoragePtr table = StorageLog::create("./", "test", "test", ColumnsDescription{names_and_types}, 1048576); table->startup(); auto context = Context::createGlobal(); + context.makeGlobalContext(); /// write into it { diff --git a/dbms/src/Storages/tests/system_numbers.cpp b/dbms/src/Storages/tests/system_numbers.cpp index 92d1f9d65e2..0ba94fb5d0a 100644 --- a/dbms/src/Storages/tests/system_numbers.cpp +++ b/dbms/src/Storages/tests/system_numbers.cpp @@ -26,9 +26,10 @@ try WriteBufferFromOStream out_buf(std::cout); - QueryProcessingStage::Enum stage = table->getQueryProcessingStage(Context::createGlobal()); - auto context = Context::createGlobal(); + context.makeGlobalContext(); + QueryProcessingStage::Enum stage = table->getQueryProcessingStage(context); + LimitBlockInputStream input(table->read(column_names, {}, context, stage, 10, 1)[0], 10, 96); BlockOutputStreamPtr out = FormatFactory::instance().getOutput("TabSeparated", out_buf, sample, context); diff --git a/dbms/src/TableFunctions/CMakeLists.txt b/dbms/src/TableFunctions/CMakeLists.txt index 9bd1374cd4d..26f9b7ddeb2 100644 --- a/dbms/src/TableFunctions/CMakeLists.txt +++ b/dbms/src/TableFunctions/CMakeLists.txt @@ -5,4 +5,4 @@ list(REMOVE_ITEM clickhouse_table_functions_sources ITableFunction.cpp TableFunc list(REMOVE_ITEM clickhouse_table_functions_headers ITableFunction.h TableFunctionFactory.h) add_library(clickhouse_table_functions ${clickhouse_table_functions_sources}) -target_link_libraries(clickhouse_table_functions PRIVATE clickhouse_storages_system dbms ${Poco_Foundation_LIBRARY}) +target_link_libraries(clickhouse_table_functions PRIVATE clickhouse_parsers clickhouse_storages_system dbms ${Poco_Foundation_LIBRARY}) diff --git a/dbms/src/TableFunctions/ITableFunction.h b/dbms/src/TableFunctions/ITableFunction.h index 026ff944976..fe08e56106b 100644 --- a/dbms/src/TableFunctions/ITableFunction.h +++ b/dbms/src/TableFunctions/ITableFunction.h @@ -26,6 +26,8 @@ class Context; class ITableFunction { public: + static inline std::string getDatabaseName() { return "_table_function"; } + /// Get the main function name. virtual std::string getName() const = 0; diff --git a/dbms/src/TableFunctions/ITableFunctionXDBC.cpp b/dbms/src/TableFunctions/ITableFunctionXDBC.cpp index 32011dc8f8a..6548dcc1acb 100644 --- a/dbms/src/TableFunctions/ITableFunctionXDBC.cpp +++ b/dbms/src/TableFunctions/ITableFunctionXDBC.cpp @@ -76,7 +76,7 @@ StoragePtr ITableFunctionXDBC::executeImpl(const ASTPtr & ast_function, const Co readStringBinary(columns_info, buf); NamesAndTypesList columns = NamesAndTypesList::parse(columns_info); - auto result = std::make_shared(table_name, schema_name, table_name, ColumnsDescription{columns}, context, helper); + auto result = std::make_shared(getDatabaseName(), table_name, schema_name, table_name, ColumnsDescription{columns}, context, helper); if (!result) throw Exception("Failed to instantiate storage from table function " + getName(), ErrorCodes::UNKNOWN_EXCEPTION); diff --git a/dbms/src/TableFunctions/TableFunctionCatBoostPool.cpp b/dbms/src/TableFunctions/TableFunctionCatBoostPool.cpp index 23ff34be827..da926dcc906 100644 --- a/dbms/src/TableFunctions/TableFunctionCatBoostPool.cpp +++ b/dbms/src/TableFunctions/TableFunctionCatBoostPool.cpp @@ -45,7 +45,7 @@ StoragePtr TableFunctionCatBoostPool::executeImpl(const ASTPtr & ast_function, c String column_descriptions_file = getStringLiteral(*args[0], "Column descriptions file"); String dataset_description_file = getStringLiteral(*args[1], "Dataset description file"); - return StorageCatBoostPool::create(context, column_descriptions_file, dataset_description_file); + return StorageCatBoostPool::create(getDatabaseName(), getName(), context, column_descriptions_file, dataset_description_file); } void registerTableFunctionCatBoostPool(TableFunctionFactory & factory) diff --git a/dbms/src/TableFunctions/TableFunctionFile.cpp b/dbms/src/TableFunctions/TableFunctionFile.cpp index 89531096d35..c1fed19101a 100644 --- a/dbms/src/TableFunctions/TableFunctionFile.cpp +++ b/dbms/src/TableFunctions/TableFunctionFile.cpp @@ -10,6 +10,7 @@ StoragePtr TableFunctionFile::getStorage( return StorageFile::create(source, -1, global_context.getUserFilesPath(), + getDatabaseName(), getName(), format, ColumnsDescription{sample_block.getNamesAndTypesList()}, diff --git a/dbms/src/TableFunctions/TableFunctionHDFS.cpp b/dbms/src/TableFunctions/TableFunctionHDFS.cpp index 9c09ad9313c..7396b477cd1 100644 --- a/dbms/src/TableFunctions/TableFunctionHDFS.cpp +++ b/dbms/src/TableFunctions/TableFunctionHDFS.cpp @@ -11,6 +11,7 @@ StoragePtr TableFunctionHDFS::getStorage( const String & source, const String & format, const Block & sample_block, Context & global_context) const { return StorageHDFS::create(source, + getDatabaseName(), getName(), format, ColumnsDescription{sample_block.getNamesAndTypesList()}, diff --git a/dbms/src/TableFunctions/TableFunctionMerge.cpp b/dbms/src/TableFunctions/TableFunctionMerge.cpp index cd8d906b94d..d446c8d723e 100644 --- a/dbms/src/TableFunctions/TableFunctionMerge.cpp +++ b/dbms/src/TableFunctions/TableFunctionMerge.cpp @@ -70,6 +70,7 @@ StoragePtr TableFunctionMerge::executeImpl(const ASTPtr & ast_function, const Co String table_name_regexp = args[1]->as().value.safeGet(); auto res = StorageMerge::create( + getDatabaseName(), getName(), ColumnsDescription{chooseColumns(source_database, table_name_regexp, context)}, source_database, diff --git a/dbms/src/TableFunctions/TableFunctionMySQL.cpp b/dbms/src/TableFunctions/TableFunctionMySQL.cpp index 71d195e95ed..8bba0388933 100644 --- a/dbms/src/TableFunctions/TableFunctionMySQL.cpp +++ b/dbms/src/TableFunctions/TableFunctionMySQL.cpp @@ -119,6 +119,7 @@ StoragePtr TableFunctionMySQL::executeImpl(const ASTPtr & ast_function, const Co throw Exception("MySQL table " + backQuoteIfNeed(database_name) + "." + backQuoteIfNeed(table_name) + " doesn't exist.", ErrorCodes::UNKNOWN_TABLE); auto res = StorageMySQL::create( + getDatabaseName(), table_name, std::move(pool), database_name, diff --git a/dbms/src/TableFunctions/TableFunctionURL.cpp b/dbms/src/TableFunctions/TableFunctionURL.cpp index f33e5a92cb3..d5d9168aed8 100644 --- a/dbms/src/TableFunctions/TableFunctionURL.cpp +++ b/dbms/src/TableFunctions/TableFunctionURL.cpp @@ -9,7 +9,7 @@ StoragePtr TableFunctionURL::getStorage( const String & source, const String & format, const Block & sample_block, Context & global_context) const { Poco::URI uri(source); - return StorageURL::create(uri, getName(), format, ColumnsDescription{sample_block.getNamesAndTypesList()}, global_context); + return StorageURL::create(uri, getDatabaseName(), getName(), format, ColumnsDescription{sample_block.getNamesAndTypesList()}, global_context); } void registerTableFunctionURL(TableFunctionFactory & factory) diff --git a/dbms/tests/instructions/sanitizers.md b/dbms/tests/instructions/sanitizers.md index f71d469182d..c21ff9b0a9b 100644 --- a/dbms/tests/instructions/sanitizers.md +++ b/dbms/tests/instructions/sanitizers.md @@ -66,4 +66,6 @@ sudo -u clickhouse UBSAN_OPTIONS='print_stacktrace=1' ./clickhouse-ubsan server # How to use Memory Sanitizer -TODO +``` +CC=clang-8 CXX=clang++-8 cmake -D ENABLE_HDFS=0 -D ENABLE_CAPNP=0 -D ENABLE_RDKAFKA=0 -D ENABLE_ICU=0 -D ENABLE_POCO_MONGODB=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_POCO_ODBC=0 -D ENABLE_ODBC=0 -D ENABLE_MYSQL=0 -D ENABLE_EMBEDDED_COMPILER=0 -D USE_INTERNAL_CAPNP_LIBRARY=0 -D USE_INTERNAL_SSL_LIBRARY=0 -D USE_SIMDJSON=0 -DENABLE_READLINE=0 -D SANITIZE=memory .. +``` diff --git a/dbms/tests/integration/README.md b/dbms/tests/integration/README.md index 1b2d190b383..06819af7668 100644 --- a/dbms/tests/integration/README.md +++ b/dbms/tests/integration/README.md @@ -12,7 +12,7 @@ You must install latest Docker from https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/#set-up-the-repository Don't use Docker from your system repository. -* [pip](https://pypi.python.org/pypi/pip). To install: `sudo apt-get install python-pip` +* [pip](https://pypi.python.org/pypi/pip) and `libpq-dev`. To install: `sudo apt-get install python-pip libpq-dev` * [py.test](https://docs.pytest.org/) testing framework. To install: `sudo -H pip install pytest` * [docker-compose](https://docs.docker.com/compose/) and additional python libraries. To install: `sudo -H pip install docker-compose docker dicttoxml kazoo PyMySQL psycopg2 pymongo tzlocal kafka-python protobuf pytest-timeout` diff --git a/dbms/tests/integration/helpers/cluster.py b/dbms/tests/integration/helpers/cluster.py index 157ba616246..fbc6591eaa5 100644 --- a/dbms/tests/integration/helpers/cluster.py +++ b/dbms/tests/integration/helpers/cluster.py @@ -114,7 +114,7 @@ class ClickHouseCluster: cmd += " client" return cmd - def add_instance(self, name, config_dir=None, main_configs=[], user_configs=[], macros={}, with_zookeeper=False, with_mysql=False, with_kafka=False, clickhouse_path_dir=None, with_odbc_drivers=False, with_postgres=False, with_hdfs=False, with_mongo=False, hostname=None, env_variables={}, image="yandex/clickhouse-integration-test", stay_alive=False, ipv4_address=None, ipv6_address=None): + def add_instance(self, name, config_dir=None, main_configs=[], user_configs=[], macros={}, with_zookeeper=False, with_mysql=False, with_kafka=False, clickhouse_path_dir=None, with_odbc_drivers=False, with_postgres=False, with_hdfs=False, with_mongo=False, hostname=None, env_variables={}, image="yandex/clickhouse-integration-test", stay_alive=False, ipv4_address=None, ipv6_address=None, with_installed_binary=False): """Add an instance to the cluster. name - the name of the instance directory and the value of the 'instance' macro in ClickHouse. @@ -134,7 +134,8 @@ class ClickHouseCluster: self, self.base_dir, name, config_dir, main_configs, user_configs, macros, with_zookeeper, self.zookeeper_config_path, with_mysql, with_kafka, with_mongo, self.base_configs_dir, self.server_bin_path, self.odbc_bridge_bin_path, clickhouse_path_dir, with_odbc_drivers, hostname=hostname, - env_variables=env_variables, image=image, stay_alive=stay_alive, ipv4_address=ipv4_address, ipv6_address=ipv6_address) + env_variables=env_variables, image=image, stay_alive=stay_alive, ipv4_address=ipv4_address, ipv6_address=ipv6_address, + with_installed_binary=with_installed_binary) self.instances[name] = instance if ipv4_address is not None or ipv6_address is not None: @@ -338,30 +339,32 @@ class ClickHouseCluster: self.docker_client = docker.from_env(version=self.docker_api_version) + common_opts = ['up', '-d', '--force-recreate'] + if self.with_zookeeper and self.base_zookeeper_cmd: - subprocess_check_call(self.base_zookeeper_cmd + ['up', '-d', '--force-recreate']) + subprocess_check_call(self.base_zookeeper_cmd + common_opts) for command in self.pre_zookeeper_commands: self.run_kazoo_commands_with_retries(command, repeats=5) self.wait_zookeeper_to_start(120) if self.with_mysql and self.base_mysql_cmd: - subprocess_check_call(self.base_mysql_cmd + ['up', '-d', '--force-recreate']) + subprocess_check_call(self.base_mysql_cmd + common_opts) self.wait_mysql_to_start(120) if self.with_postgres and self.base_postgres_cmd: - subprocess_check_call(self.base_postgres_cmd + ['up', '-d', '--force-recreate']) + subprocess_check_call(self.base_postgres_cmd + common_opts) self.wait_postgres_to_start(120) if self.with_kafka and self.base_kafka_cmd: - subprocess_check_call(self.base_kafka_cmd + ['up', '-d', '--force-recreate']) + subprocess_check_call(self.base_kafka_cmd + common_opts + ['--renew-anon-volumes']) self.kafka_docker_id = self.get_instance_docker_id('kafka1') if self.with_hdfs and self.base_hdfs_cmd: - subprocess_check_call(self.base_hdfs_cmd + ['up', '-d', '--force-recreate']) + subprocess_check_call(self.base_hdfs_cmd + common_opts) self.wait_hdfs_to_start(120) if self.with_mongo and self.base_mongo_cmd: - subprocess_check_call(self.base_mongo_cmd + ['up', '-d', '--force-recreate']) + subprocess_check_call(self.base_mongo_cmd + common_opts) self.wait_mongo_to_start(30) subprocess_check_call(self.base_cmd + ['up', '-d', '--no-recreate']) @@ -425,11 +428,11 @@ services: image: {image} hostname: {hostname} volumes: - - {binary_path}:/usr/bin/clickhouse:ro - - {odbc_bridge_bin_path}:/usr/bin/clickhouse-odbc-bridge:ro - {configs_dir}:/etc/clickhouse-server/ - {db_dir}:/var/lib/clickhouse/ - {logs_dir}:/var/log/clickhouse-server/ + {binary_volume} + {odbc_bridge_volume} {odbc_ini_path} entrypoint: {entrypoint_cmd} cap_add: @@ -453,7 +456,7 @@ class ClickHouseInstance: self, cluster, base_path, name, custom_config_dir, custom_main_configs, custom_user_configs, macros, with_zookeeper, zookeeper_config_path, with_mysql, with_kafka, with_mongo, base_configs_dir, server_bin_path, odbc_bridge_bin_path, clickhouse_path_dir, with_odbc_drivers, hostname=None, env_variables={}, image="yandex/clickhouse-integration-test", - stay_alive=False, ipv4_address=None, ipv6_address=None): + stay_alive=False, ipv4_address=None, ipv6_address=None, with_installed_binary=False): self.name = name self.base_cmd = cluster.base_cmd[:] @@ -494,6 +497,7 @@ class ClickHouseInstance: self.stay_alive = stay_alive self.ipv4_address = ipv4_address self.ipv6_address = ipv6_address + self.with_installed_binary = with_installed_binary # Connects to the instance via clickhouse-client, sends a query (1st argument) and returns the answer def query(self, sql, stdin=None, timeout=None, settings=None, user=None, ignore_error=False): @@ -533,7 +537,7 @@ class ClickHouseInstance: self.exec_in_container(["bash", "-c", "pkill clickhouse"], user='root') time.sleep(stop_start_wait_sec) - self.exec_in_container(["bash", "-c", "{} --daemon".format(CLICKHOUSE_START_COMMAND)], user='root') + self.exec_in_container(["bash", "-c", "{} --daemon".format(CLICKHOUSE_START_COMMAND)], user=str(os.getuid())) def exec_in_container(self, cmd, detach=False, **kwargs): container = self.get_docker_handle() @@ -556,8 +560,39 @@ class ClickHouseInstance: encoded_data = base64.b64encode(data) self.exec_in_container(["bash", "-c", "echo {} | base64 --decode > {}".format(encoded_data, dest_path)]) + def get_process_pid(self, process_name): + output = self.exec_in_container(["bash", "-c", "ps ax | grep '{}' | grep -v 'grep' | grep -v 'bash -c' | awk '{{print $1}}'".format(process_name)]) + if output: + try: + pid = int(output.split('\n')[0].strip()) + return pid + except: + return None + return None + def restart_with_latest_version(self, stop_start_wait_sec=10, callback_onstop=None, signal=15): + if not self.stay_alive: + raise Exception("Cannot restart not stay alive container") + self.exec_in_container(["bash", "-c", "pkill -{} clickhouse".format(signal)], user='root') + retries = int(stop_start_wait_sec / 0.5) + local_counter = 0 + # wait stop + while local_counter < retries: + if not self.get_process_pid("clickhouse server"): + break + time.sleep(0.5) + local_counter += 1 + + if callback_onstop: + callback_onstop(self) + self.exec_in_container(["bash", "-c", "cp /usr/share/clickhouse_fresh /usr/bin/clickhouse && chmod 777 /usr/bin/clickhouse"], user='root') + self.exec_in_container(["bash", "-c", "cp /usr/share/clickhouse-odbc-bridge_fresh /usr/bin/clickhouse-odbc-bridge && chmod 777 /usr/bin/clickhouse"], user='root') + self.exec_in_container(["bash", "-c", "{} --daemon".format(CLICKHOUSE_START_COMMAND)], user=str(os.getuid())) + from helpers.test_tools import assert_eq_with_retry + # wait start + assert_eq_with_retry(self, "select 1", "1", retry_count=retries) + def get_docker_handle(self): return self.docker_client.containers.get(self.docker_id) @@ -656,6 +691,9 @@ class ClickHouseInstance: if key != "DSN": f.write(key + "=" + value + "\n") + def replace_config(self, path_to_config, replacement): + self.exec_in_container(["bash", "-c", "echo '{}' > {}".format(replacement, path_to_config)]) + def create_dir(self, destroy_dir=True): """Create the instance directory and all the needed files there.""" @@ -750,13 +788,21 @@ class ClickHouseInstance: if self.ipv6_address is not None: ipv6_address = "ipv6_address: " + self.ipv6_address + if not self.with_installed_binary: + binary_volume = "- " + self.server_bin_path + ":/usr/bin/clickhouse" + odbc_bridge_volume = "- " + self.odbc_bridge_bin_path + ":/usr/bin/clickhouse-odbc-bridge" + else: + binary_volume = "- " + self.server_bin_path + ":/usr/share/clickhouse_fresh" + odbc_bridge_volume = "- " + self.odbc_bridge_bin_path + ":/usr/share/clickhouse-odbc-bridge_fresh" + + with open(self.docker_compose_path, 'w') as docker_compose: docker_compose.write(DOCKER_COMPOSE_TEMPLATE.format( image=self.image, name=self.name, hostname=self.hostname, - binary_path=self.server_bin_path, - odbc_bridge_bin_path=self.odbc_bridge_bin_path, + binary_volume=binary_volume, + odbc_bridge_volume=odbc_bridge_volume, configs_dir=configs_dir, config_d_dir=config_d_dir, db_dir=db_dir, diff --git a/dbms/tests/integration/test_adaptive_granularity/__init__.py b/dbms/tests/integration/test_adaptive_granularity/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dbms/tests/integration/test_adaptive_granularity/configs/log_conf.xml b/dbms/tests/integration/test_adaptive_granularity/configs/log_conf.xml new file mode 100644 index 00000000000..318a6bca95d --- /dev/null +++ b/dbms/tests/integration/test_adaptive_granularity/configs/log_conf.xml @@ -0,0 +1,12 @@ + + 3 + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + diff --git a/dbms/tests/integration/test_adaptive_granularity/configs/merge_tree_settings.xml b/dbms/tests/integration/test_adaptive_granularity/configs/merge_tree_settings.xml new file mode 100644 index 00000000000..31ede39c318 --- /dev/null +++ b/dbms/tests/integration/test_adaptive_granularity/configs/merge_tree_settings.xml @@ -0,0 +1,4 @@ + + + + diff --git a/dbms/tests/integration/test_adaptive_granularity/configs/remote_servers.xml b/dbms/tests/integration/test_adaptive_granularity/configs/remote_servers.xml new file mode 100644 index 00000000000..8c77a7afe54 --- /dev/null +++ b/dbms/tests/integration/test_adaptive_granularity/configs/remote_servers.xml @@ -0,0 +1,68 @@ + + + + + + true + + test + node1 + 9000 + + + test + node2 + 9000 + + + + + + + true + + test + node3 + 9000 + + + test + node4 + 9000 + + + + + + + true + + test + node5 + 9000 + + + test + node6 + 9000 + + + + + + + true + + test + node11 + 9000 + + + test + node12 + 9000 + + + + + diff --git a/dbms/tests/integration/test_adaptive_granularity/test.py b/dbms/tests/integration/test_adaptive_granularity/test.py new file mode 100644 index 00000000000..db653427f02 --- /dev/null +++ b/dbms/tests/integration/test_adaptive_granularity/test.py @@ -0,0 +1,329 @@ +import time +import pytest + +from helpers.cluster import ClickHouseCluster +from multiprocessing.dummy import Pool +from helpers.client import QueryRuntimeException, QueryTimeoutExceedException + +from helpers.test_tools import assert_eq_with_retry + + +cluster = ClickHouseCluster(__file__) +node1 = cluster.add_instance('node1', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True) +node2 = cluster.add_instance('node2', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True) + +node3 = cluster.add_instance('node3', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True, image='yandex/clickhouse-server:19.6.3.18', with_installed_binary=True) +node4 = cluster.add_instance('node4', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True) + +node5 = cluster.add_instance('node5', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True, image='yandex/clickhouse-server:19.1.15', with_installed_binary=True) +node6 = cluster.add_instance('node6', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True) + +node7 = cluster.add_instance('node7', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True, image='yandex/clickhouse-server:19.6.3.18', stay_alive=True, with_installed_binary=True) +node8 = cluster.add_instance('node8', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True, image='yandex/clickhouse-server:19.1.15', stay_alive=True, with_installed_binary=True) + +node9 = cluster.add_instance('node9', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml', 'configs/merge_tree_settings.xml'], with_zookeeper=True, image='yandex/clickhouse-server:19.1.15', stay_alive=True, with_installed_binary=True) +node10 = cluster.add_instance('node10', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml', 'configs/merge_tree_settings.xml'], with_zookeeper=True, image='yandex/clickhouse-server:19.6.3.18', stay_alive=True, with_installed_binary=True) + +node11 = cluster.add_instance('node11', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True, image='yandex/clickhouse-server:19.1.15', stay_alive=True, with_installed_binary=True) +node12 = cluster.add_instance('node12', config_dir="configs", main_configs=['configs/remote_servers.xml', 'configs/log_conf.xml'], with_zookeeper=True, image='yandex/clickhouse-server:19.1.15', stay_alive=True, with_installed_binary=True) + + +def prepare_single_pair_with_setting(first_node, second_node, group): + for node in (first_node, second_node): + node.query("CREATE DATABASE IF NOT EXISTS test") + + # Two tables with adaptive granularity + first_node.query( + ''' + CREATE TABLE table_by_default(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/{g}/table_by_default', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + SETTINGS index_granularity_bytes = 10485760 + '''.format(g=group)) + + second_node.query( + ''' + CREATE TABLE table_by_default(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/{g}/table_by_default', '2') + PARTITION BY toYYYYMM(date) + ORDER BY id + SETTINGS index_granularity_bytes = 10485760 + '''.format(g=group)) + + # Two tables with fixed granularity + first_node.query( + ''' + CREATE TABLE table_with_fixed_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/{g}/table_with_fixed_granularity', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + SETTINGS index_granularity_bytes = 0 + '''.format(g=group)) + + second_node.query( + ''' + CREATE TABLE table_with_fixed_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/{g}/table_with_fixed_granularity', '2') + PARTITION BY toYYYYMM(date) + ORDER BY id + SETTINGS index_granularity_bytes = 0 + '''.format(g=group)) + + # Two tables with different granularity + with pytest.raises(QueryRuntimeException): + first_node.query( + ''' + CREATE TABLE table_with_different_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/{g}/table_with_different_granularity', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + SETTINGS index_granularity_bytes = 10485760 + '''.format(g=group)) + + second_node.query( + ''' + CREATE TABLE table_with_different_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/{g}/table_with_different_granularity', '2') + PARTITION BY toYYYYMM(date) + ORDER BY id + SETTINGS index_granularity_bytes = 0 + '''.format(g=group)) + + # Two tables with different granularity, but enabled mixed parts + first_node.query( + ''' + CREATE TABLE table_with_mixed_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/{g}/table_with_mixed_granularity', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + SETTINGS index_granularity_bytes = 10485760, enable_mixed_granularity_parts=1 + '''.format(g=group)) + + second_node.query( + ''' + CREATE TABLE table_with_mixed_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/{g}/table_with_mixed_granularity', '2') + PARTITION BY toYYYYMM(date) + ORDER BY id + SETTINGS index_granularity_bytes = 0, enable_mixed_granularity_parts=1 + '''.format(g=group)) + + +def prepare_single_pair_without_setting(first_node, second_node, group): + for node in (first_node, second_node): + node.query("CREATE DATABASE IF NOT EXISTS test") + + # Two tables with fixed granularity + first_node.query( + ''' + CREATE TABLE table_with_fixed_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/{g}/table_with_fixed_granularity', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + '''.format(g=group)) + + second_node.query( + ''' + CREATE TABLE table_with_fixed_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/{g}/table_with_fixed_granularity', '2') + PARTITION BY toYYYYMM(date) + ORDER BY id + SETTINGS index_granularity_bytes = 0 + '''.format(g=group)) + + +@pytest.fixture(scope="module") +def start_static_cluster(): + try: + cluster.start() + + prepare_single_pair_with_setting(node1, node2, "shard1") + prepare_single_pair_with_setting(node3, node4, "shard2") + prepare_single_pair_without_setting(node5, node6, "shard3") + yield cluster + + finally: + cluster.shutdown() + + +@pytest.mark.parametrize( + ('first_node', 'second_node', 'table'), + [ + (node1, node2, 'table_by_default'), + (node1, node2, 'table_with_fixed_granularity'), + (node3, node4, 'table_by_default'), + (node3, node4, 'table_with_fixed_granularity'), + (node5, node6, 'table_with_fixed_granularity'), + ] +) +def test_different_versions_cluster(start_static_cluster, first_node, second_node, table): + counter = 1 + for n1, n2 in ((first_node, second_node), (second_node, first_node)): + n1.query("INSERT INTO {tbl} VALUES (toDate('2018-10-01'), {c1}, 333), (toDate('2018-10-02'), {c2}, 444)".format(tbl=table, c1=counter * 2, c2=counter * 2 + 1)) + n2.query("SYSTEM SYNC REPLICA {tbl}".format(tbl=table)) + assert_eq_with_retry(n2, "SELECT count() from {tbl}".format(tbl=table), str(counter * 2)) + n1.query("DETACH TABLE {tbl}".format(tbl=table)) + n2.query("DETACH TABLE {tbl}".format(tbl=table)) + n1.query("ATTACH TABLE {tbl}".format(tbl=table)) + n2.query("ATTACH TABLE {tbl}".format(tbl=table)) + assert_eq_with_retry(n1, "SELECT count() from {tbl}".format(tbl=table), str(counter * 2)) + assert_eq_with_retry(n2, "SELECT count() from {tbl}".format(tbl=table), str(counter * 2)) + n1.query("OPTIMIZE TABLE {tbl} FINAL".format(tbl=table)) + n2.query("SYSTEM SYNC REPLICA {tbl}".format(tbl=table)) + assert_eq_with_retry(n1, "SELECT count() from {tbl}".format(tbl=table), str(counter * 2)) + assert_eq_with_retry(n2, "SELECT count() from {tbl}".format(tbl=table), str(counter * 2)) + counter += 1 + +@pytest.fixture(scope="module") +def start_dynamic_cluster(): + try: + cluster.start() + node7.query( + ''' + CREATE TABLE table_with_default_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/7/table_with_default_granularity', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + ''') + + node7.query( + ''' + CREATE TABLE table_with_adaptive_default_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/7/table_with_adaptive_default_granularity', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + SETTINGS index_granularity_bytes=10485760 + ''') + + node8.query( + ''' + CREATE TABLE table_with_default_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/8/table_with_default_granularity', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + ''') + + node9.query( + ''' + CREATE TABLE table_with_default_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/9/table_with_default_granularity', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + ''') + + node10.query( + ''' + CREATE TABLE table_with_default_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/10/table_with_default_granularity', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + ''') + + node11.query( + ''' + CREATE TABLE table_with_default_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/shard11/table_with_default_granularity', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + ''') + + node12.query( + ''' + CREATE TABLE table_with_default_granularity(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/shard11/table_with_default_granularity', '2') + PARTITION BY toYYYYMM(date) + ORDER BY id + ''') + + + yield cluster + + finally: + cluster.shutdown() + +@pytest.mark.parametrize( + ('n', 'tables'), + [ + (node7, ['table_with_default_granularity', 'table_with_adaptive_default_granularity']), + (node8, ['table_with_default_granularity']), + ] +) +def test_version_single_node_update(start_dynamic_cluster, n, tables): + for table in tables: + n.query("INSERT INTO {tbl} VALUES (toDate('2018-10-01'), 1, 333), (toDate('2018-10-02'), 2, 444)".format(tbl=table)) + n.restart_with_latest_version() + for table in tables: + assert n.query("SELECT count() from {tbl}".format(tbl=table)) == '2\n' + n.query("INSERT INTO {tbl} VALUES (toDate('2018-10-01'), 3, 333), (toDate('2018-10-02'), 4, 444)".format(tbl=table)) + assert n.query("SELECT count() from {tbl}".format(tbl=table)) == '4\n' + +@pytest.mark.parametrize( + ('node',), + [ + (node9,), + (node10,) + ] +) +def test_mixed_granularity_single_node(start_dynamic_cluster, node): + node.query("INSERT INTO table_with_default_granularity VALUES (toDate('2018-10-01'), 1, 333), (toDate('2018-10-02'), 2, 444)") + node.query("INSERT INTO table_with_default_granularity VALUES (toDate('2018-09-01'), 1, 333), (toDate('2018-09-02'), 2, 444)") + + def callback(n): + n.replace_config("/etc/clickhouse-server/merge_tree_settings.xml", "1") + n.replace_config("/etc/clickhouse-server/config.d/merge_tree_settings.xml", "1") + + node.restart_with_latest_version(callback_onstop=callback) + node.query("SYSTEM RELOAD CONFIG") + assert_eq_with_retry(node, "SELECT value FROM system.merge_tree_settings WHERE name='enable_mixed_granularity_parts'", '1') + assert node.query("SELECT count() from table_with_default_granularity") == '4\n' + node.query("INSERT INTO table_with_default_granularity VALUES (toDate('2018-10-01'), 3, 333), (toDate('2018-10-02'), 4, 444)") + assert node.query("SELECT count() from table_with_default_granularity") == '6\n' + node.query("OPTIMIZE TABLE table_with_default_granularity PARTITION 201810 FINAL") + assert node.query("SELECT count() from table_with_default_granularity") == '6\n' + path_to_merged_part = node.query("SELECT path FROM system.parts WHERE table = 'table_with_default_granularity' AND active=1 ORDER BY partition DESC LIMIT 1").strip() + node.exec_in_container(["bash", "-c", "find {p} -name '*.mrk2' | grep '.*'".format(p=path_to_merged_part)]) # check that we have adaptive files + + path_to_old_part = node.query("SELECT path FROM system.parts WHERE table = 'table_with_default_granularity' AND active=1 ORDER BY partition ASC LIMIT 1").strip() + + node.exec_in_container(["bash", "-c", "find {p} -name '*.mrk' | grep '.*'".format(p=path_to_old_part)]) # check that we have non adaptive files + +def test_version_update_two_nodes(start_dynamic_cluster): + node11.query("INSERT INTO table_with_default_granularity VALUES (toDate('2018-10-01'), 1, 333), (toDate('2018-10-02'), 2, 444)") + node12.query("SYSTEM SYNC REPLICA table_with_default_granularity") + assert node12.query("SELECT COUNT() FROM table_with_default_granularity") == '2\n' + node12.restart_with_latest_version() + node12.query("INSERT INTO table_with_default_granularity VALUES (toDate('2018-10-01'), 3, 333), (toDate('2018-10-02'), 4, 444)") + node11.query("SYSTEM SYNC REPLICA table_with_default_granularity") + assert node11.query("SELECT COUNT() FROM table_with_default_granularity") == '4\n' + + node12.query( + ''' + CREATE TABLE table_with_default_granularity_new(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/shard11/table_with_default_granularity_new', '2') + PARTITION BY toYYYYMM(date) + ORDER BY id + ''') + + node11.query( + ''' + CREATE TABLE table_with_default_granularity_new(date Date, id UInt32, dummy UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/shard11/table_with_default_granularity_new', '1') + PARTITION BY toYYYYMM(date) + ORDER BY id + ''') + + node12.query("INSERT INTO table_with_default_granularity_new VALUES (toDate('2018-10-01'), 1, 333), (toDate('2018-10-02'), 2, 444)") + with pytest.raises(QueryTimeoutExceedException): + node11.query("SYSTEM SYNC REPLICA table_with_default_granularity_new", timeout=5) + node12.query("INSERT INTO table_with_default_granularity_new VALUES (toDate('2018-10-01'), 3, 333), (toDate('2018-10-02'), 4, 444)") + + node11.restart_with_latest_version(signal=9) # just to be sure + node11.query("SYSTEM SYNC REPLICA table_with_default_granularity_new", timeout=5) + node12.query("SYSTEM SYNC REPLICA table_with_default_granularity_new", timeout=5) + node11.query("SELECT COUNT() FROM table_with_default_granularity_new") == "4\n" + node12.query("SELECT COUNT() FROM table_with_default_granularity_new") == "4\n" + + node11.query("INSERT INTO table_with_default_granularity VALUES (toDate('2018-10-01'), 5, 333), (toDate('2018-10-02'), 6, 444)") + node12.query("SYSTEM SYNC REPLICA table_with_default_granularity") + assert node12.query("SELECT COUNT() FROM table_with_default_granularity") == '6\n' diff --git a/dbms/tests/integration/test_check_table/__init__.py b/dbms/tests/integration/test_check_table/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dbms/tests/integration/test_check_table/test.py b/dbms/tests/integration/test_check_table/test.py new file mode 100644 index 00000000000..6d53b423896 --- /dev/null +++ b/dbms/tests/integration/test_check_table/test.py @@ -0,0 +1,129 @@ +import time + +import pytest + +from helpers.cluster import ClickHouseCluster +from helpers.test_tools import assert_eq_with_retry + +cluster = ClickHouseCluster(__file__) + +node1 = cluster.add_instance('node1', with_zookeeper=True) +node2 = cluster.add_instance('node2', with_zookeeper=True) + + +@pytest.fixture(scope="module") +def started_cluster(): + try: + cluster.start() + + for node in [node1, node2]: + node.query(''' + CREATE TABLE replicated_mt(date Date, id UInt32, value Int32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/replicated_mt', '{replica}') PARTITION BY toYYYYMM(date) ORDER BY id; + '''.format(replica=node.name)) + + node1.query(''' + CREATE TABLE non_replicated_mt(date Date, id UInt32, value Int32) + ENGINE = MergeTree() PARTITION BY toYYYYMM(date) ORDER BY id; + ''') + + yield cluster + + finally: + cluster.shutdown() + + +def corrupt_data_part_on_disk(node, table, part_name): + part_path = node.query("SELECT path FROM system.parts WHERE table = '{}' and name = '{}'".format(table, part_name)).strip() + node.exec_in_container(['bash', '-c', 'cd {p} && ls *.bin | head -n 1 | xargs -I{{}} sh -c \'echo "1" >> $1\' -- {{}}'.format(p=part_path)], privileged=True) + +def remove_checksums_on_disk(node, table, part_name): + part_path = node.query("SELECT path FROM system.parts WHERE table = '{}' and name = '{}'".format(table, part_name)).strip() + node.exec_in_container(['bash', '-c', 'rm -r {p}/checksums.txt'.format(p=part_path)], privileged=True) + +def remove_part_from_disk(node, table, part_name): + part_path = node.query("SELECT path FROM system.parts WHERE table = '{}' and name = '{}'".format(table, part_name)).strip() + if not part_path: + raise Exception("Part " + part_name + "doesn't exist") + node.exec_in_container(['bash', '-c', 'rm -r {p}/*'.format(p=part_path)], privileged=True) + + +def test_check_normal_table_corruption(started_cluster): + node1.query("INSERT INTO non_replicated_mt VALUES (toDate('2019-02-01'), 1, 10), (toDate('2019-02-01'), 2, 12)") + assert node1.query("CHECK TABLE non_replicated_mt PARTITION 201902") == "201902_1_1_0\t1\t\n" + + remove_checksums_on_disk(node1, "non_replicated_mt", "201902_1_1_0") + + assert node1.query("CHECK TABLE non_replicated_mt").strip() == "201902_1_1_0\t1\tChecksums recounted and written to disk." + + assert node1.query("SELECT COUNT() FROM non_replicated_mt") == "2\n" + + remove_checksums_on_disk(node1, "non_replicated_mt", "201902_1_1_0") + + assert node1.query("CHECK TABLE non_replicated_mt PARTITION 201902").strip() == "201902_1_1_0\t1\tChecksums recounted and written to disk." + + assert node1.query("SELECT COUNT() FROM non_replicated_mt") == "2\n" + + corrupt_data_part_on_disk(node1, "non_replicated_mt", "201902_1_1_0") + + assert node1.query("CHECK TABLE non_replicated_mt").strip() == "201902_1_1_0\t0\tCannot read all data. Bytes read: 2. Bytes expected: 16." + + assert node1.query("CHECK TABLE non_replicated_mt").strip() == "201902_1_1_0\t0\tCannot read all data. Bytes read: 2. Bytes expected: 16." + + node1.query("INSERT INTO non_replicated_mt VALUES (toDate('2019-01-01'), 1, 10), (toDate('2019-01-01'), 2, 12)") + + assert node1.query("CHECK TABLE non_replicated_mt PARTITION 201901") == "201901_2_2_0\t1\t\n" + + corrupt_data_part_on_disk(node1, "non_replicated_mt", "201901_2_2_0") + + remove_checksums_on_disk(node1, "non_replicated_mt", "201901_2_2_0") + + assert node1.query("CHECK TABLE non_replicated_mt PARTITION 201901") == "201901_2_2_0\t0\tCheck of part finished with error: \\'Cannot read all data. Bytes read: 2. Bytes expected: 16.\\'\n" + + +def test_check_replicated_table_simple(started_cluster): + node1.query("TRUNCATE TABLE replicated_mt") + node2.query("SYSTEM SYNC REPLICA replicated_mt") + node1.query("INSERT INTO replicated_mt VALUES (toDate('2019-02-01'), 1, 10), (toDate('2019-02-01'), 2, 12)") + node2.query("SYSTEM SYNC REPLICA replicated_mt") + + assert node1.query("SELECT count() from replicated_mt") == "2\n" + assert node2.query("SELECT count() from replicated_mt") == "2\n" + + assert node1.query("CHECK TABLE replicated_mt") == "201902_0_0_0\t1\t\n" + assert node2.query("CHECK TABLE replicated_mt") == "201902_0_0_0\t1\t\n" + + node2.query("INSERT INTO replicated_mt VALUES (toDate('2019-01-02'), 3, 10), (toDate('2019-01-02'), 4, 12)") + node1.query("SYSTEM SYNC REPLICA replicated_mt") + assert node1.query("SELECT count() from replicated_mt") == "4\n" + assert node2.query("SELECT count() from replicated_mt") == "4\n" + + assert node1.query("CHECK TABLE replicated_mt PARTITION 201901") == "201901_0_0_0\t1\t\n" + assert node2.query("CHECK TABLE replicated_mt PARTITION 201901") == "201901_0_0_0\t1\t\n" + + +def test_check_replicated_table_corruption(started_cluster): + node1.query("TRUNCATE TABLE replicated_mt") + node2.query("SYSTEM SYNC REPLICA replicated_mt") + node1.query("INSERT INTO replicated_mt VALUES (toDate('2019-02-01'), 1, 10), (toDate('2019-02-01'), 2, 12)") + node1.query("INSERT INTO replicated_mt VALUES (toDate('2019-01-02'), 3, 10), (toDate('2019-01-02'), 4, 12)") + node2.query("SYSTEM SYNC REPLICA replicated_mt") + + assert node1.query("SELECT count() from replicated_mt") == "4\n" + assert node2.query("SELECT count() from replicated_mt") == "4\n" + + part_name = node1.query("SELECT name from system.parts where table = 'replicated_mt' and partition_id = '201901' and active = 1").strip() + + corrupt_data_part_on_disk(node1, "replicated_mt", part_name) + assert node1.query("CHECK TABLE replicated_mt PARTITION 201901") == "{p}\t0\tPart {p} looks broken. Removing it and queueing a fetch.\n".format(p=part_name) + + node1.query("SYSTEM SYNC REPLICA replicated_mt") + assert node1.query("CHECK TABLE replicated_mt PARTITION 201901") == "{}\t1\t\n".format(part_name) + assert node1.query("SELECT count() from replicated_mt") == "4\n" + + remove_part_from_disk(node2, "replicated_mt", part_name) + assert node2.query("CHECK TABLE replicated_mt PARTITION 201901") == "{p}\t0\tPart {p} looks broken. Removing it and queueing a fetch.\n".format(p=part_name) + + node1.query("SYSTEM SYNC REPLICA replicated_mt") + assert node1.query("CHECK TABLE replicated_mt PARTITION 201901") == "{}\t1\t\n".format(part_name) + assert node1.query("SELECT count() from replicated_mt") == "4\n" diff --git a/dbms/tests/integration/test_external_dictionaries/configs/config.xml b/dbms/tests/integration/test_external_dictionaries/configs/config.xml index 97cbaf97d4a..fb8f0e1312e 100644 --- a/dbms/tests/integration/test_external_dictionaries/configs/config.xml +++ b/dbms/tests/integration/test_external_dictionaries/configs/config.xml @@ -1,12 +1,14 @@ - trace - /var/log/clickhouse-server/clickhouse-server.log - /var/log/clickhouse-server/clickhouse-server.err.log - 1000M - 10 - + trace + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + 9000 127.0.0.1 diff --git a/dbms/tests/integration/test_host_ip_change/configs/dns_update_long.xml b/dbms/tests/integration/test_host_ip_change/configs/dns_update_long.xml new file mode 100644 index 00000000000..133e3cf725a --- /dev/null +++ b/dbms/tests/integration/test_host_ip_change/configs/dns_update_long.xml @@ -0,0 +1,3 @@ + + 200 + diff --git a/dbms/tests/integration/test_host_ip_change/configs/dns_update_short.xml b/dbms/tests/integration/test_host_ip_change/configs/dns_update_short.xml new file mode 100644 index 00000000000..2bfafe2ef21 --- /dev/null +++ b/dbms/tests/integration/test_host_ip_change/configs/dns_update_short.xml @@ -0,0 +1,3 @@ + + 2 + diff --git a/dbms/tests/integration/test_host_ip_change/configs/remote_servers.xml b/dbms/tests/integration/test_host_ip_change/configs/remote_servers.xml index 538aa72d386..1b9356d59bd 100644 --- a/dbms/tests/integration/test_host_ip_change/configs/remote_servers.xml +++ b/dbms/tests/integration/test_host_ip_change/configs/remote_servers.xml @@ -1,14 +1,13 @@ - - - true - - shard_0 - node1 - 9000 - - - + + + false + + lost_host + 9000 + + + diff --git a/dbms/tests/integration/test_host_ip_change/test.py b/dbms/tests/integration/test_host_ip_change/test.py index 19280720488..3db6331f344 100644 --- a/dbms/tests/integration/test_host_ip_change/test.py +++ b/dbms/tests/integration/test_host_ip_change/test.py @@ -4,28 +4,33 @@ import pytest import subprocess from helpers.cluster import ClickHouseCluster from helpers.test_tools import assert_eq_with_retry +from helpers.client import QueryRuntimeException +from helpers.test_tools import TSV cluster = ClickHouseCluster(__file__) -node1 = cluster.add_instance('node1', main_configs=['configs/remote_servers.xml', 'configs/listen_host.xml'], with_zookeeper=True, ipv6_address='2001:3984:3989::1:1111') -node2 = cluster.add_instance('node2', main_configs=['configs/remote_servers.xml', 'configs/listen_host.xml'], with_zookeeper=True, ipv6_address='2001:3984:3989::1:1112') +def _fill_nodes(nodes, table_name): + for node in nodes: + node.query( + ''' + CREATE DATABASE IF NOT EXISTS test; + CREATE TABLE IF NOT EXISTS {0}(date Date, id UInt32) + ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/{0}', '{1}') + ORDER BY id PARTITION BY toYYYYMM(date); + '''.format(table_name, node.name) + ) +node1 = cluster.add_instance('node1', main_configs=['configs/listen_host.xml'], with_zookeeper=True, ipv6_address='2001:3984:3989::1:1111') +node2 = cluster.add_instance('node2', main_configs=['configs/listen_host.xml', 'configs/dns_update_long.xml'], + with_zookeeper=True, ipv6_address='2001:3984:3989::1:1112') @pytest.fixture(scope="module") -def start_cluster(): +def cluster_without_dns_cache_update(): try: cluster.start() - for node in [node1, node2]: - node.query( - ''' - CREATE DATABASE IF NOT EXISTS test; - CREATE TABLE IF NOT EXISTS test_table(date Date, id UInt32) - ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/replicated', '{}') - ORDER BY id PARTITION BY toYYYYMM(date); - '''.format(node.name) - ) + _fill_nodes([node1, node2], 'test_table_drop') yield cluster @@ -36,31 +41,101 @@ def start_cluster(): cluster.shutdown() pass - -def test_merge_doesnt_work_without_zookeeper(start_cluster): +# node1 is a source, node2 downloads data +# node2 has long dns_cache_update_period, so dns cache update wouldn't work +def test_ip_change_drop_dns_cache(cluster_without_dns_cache_update): # First we check, that normal replication works - node1.query("INSERT INTO test_table VALUES ('2018-10-01', 1), ('2018-10-02', 2), ('2018-10-03', 3)") - assert node1.query("SELECT count(*) from test_table") == "3\n" - assert_eq_with_retry(node2, "SELECT count(*) from test_table", "3") + node1.query("INSERT INTO test_table_drop VALUES ('2018-10-01', 1), ('2018-10-02', 2), ('2018-10-03', 3)") + assert node1.query("SELECT count(*) from test_table_drop") == "3\n" + assert_eq_with_retry(node2, "SELECT count(*) from test_table_drop", "3") # We change source node ip cluster.restart_instance_with_ip_change(node1, "2001:3984:3989::1:7777") # Put some data to source node1 - node1.query("INSERT INTO test_table VALUES ('2018-10-01', 5), ('2018-10-02', 6), ('2018-10-03', 7)") + node1.query("INSERT INTO test_table_drop VALUES ('2018-10-01', 5), ('2018-10-02', 6), ('2018-10-03', 7)") # Check that data is placed on node1 - assert node1.query("SELECT count(*) from test_table") == "6\n" + assert node1.query("SELECT count(*) from test_table_drop") == "6\n" # Because of DNS cache dest node2 cannot download data from node1 with pytest.raises(Exception): - assert_eq_with_retry(node2, "SELECT count(*) from test_table", "6") + assert_eq_with_retry(node2, "SELECT count(*) from test_table_drop", "6") # drop DNS cache node2.query("SYSTEM DROP DNS CACHE") # Data is downloaded - assert_eq_with_retry(node2, "SELECT count(*) from test_table", "6") + assert_eq_with_retry(node2, "SELECT count(*) from test_table_drop", "6") # Just to be sure check one more time - node1.query("INSERT INTO test_table VALUES ('2018-10-01', 8)") - assert node1.query("SELECT count(*) from test_table") == "7\n" - assert_eq_with_retry(node2, "SELECT count(*) from test_table", "7") + node1.query("INSERT INTO test_table_drop VALUES ('2018-10-01', 8)") + assert node1.query("SELECT count(*) from test_table_drop") == "7\n" + assert_eq_with_retry(node2, "SELECT count(*) from test_table_drop", "7") + + +node3 = cluster.add_instance('node3', main_configs=['configs/listen_host.xml'], + with_zookeeper=True, ipv6_address='2001:3984:3989::1:1113') +node4 = cluster.add_instance('node4', main_configs=['configs/remote_servers.xml', 'configs/listen_host.xml', 'configs/dns_update_short.xml'], + with_zookeeper=True, ipv6_address='2001:3984:3989::1:1114') + +@pytest.fixture(scope="module") +def cluster_with_dns_cache_update(): + try: + cluster.start() + + _fill_nodes([node3, node4], 'test_table_update') + + yield cluster + + except Exception as ex: + print ex + + finally: + cluster.shutdown() + pass + +# node3 is a source, node4 downloads data +# node4 has short dns_cache_update_period, so testing update of dns cache +def test_ip_change_update_dns_cache(cluster_with_dns_cache_update): + # First we check, that normal replication works + node3.query("INSERT INTO test_table_update VALUES ('2018-10-01', 1), ('2018-10-02', 2), ('2018-10-03', 3)") + assert node3.query("SELECT count(*) from test_table_update") == "3\n" + assert_eq_with_retry(node4, "SELECT count(*) from test_table_update", "3") + + # We change source node ip + cluster.restart_instance_with_ip_change(node3, "2001:3984:3989::1:8888") + + # Put some data to source node3 + node3.query("INSERT INTO test_table_update VALUES ('2018-10-01', 5), ('2018-10-02', 6), ('2018-10-03', 7)") + # Check that data is placed on node3 + assert node3.query("SELECT count(*) from test_table_update") == "6\n" + + # Because of DNS cache update, ip of node3 would be updated + assert_eq_with_retry(node4, "SELECT count(*) from test_table_update", "6") + + # Just to be sure check one more time + node3.query("INSERT INTO test_table_update VALUES ('2018-10-01', 8)") + assert node3.query("SELECT count(*) from test_table_update") == "7\n" + assert_eq_with_retry(node4, "SELECT count(*) from test_table_update", "7") + +def test_dns_cache_update(cluster_with_dns_cache_update): + node4.exec_in_container(['bash', '-c', 'echo 127.0.0.1 localhost > /etc/hosts'], privileged=True, user='root') + node4.exec_in_container(['bash', '-c', 'echo ::1 localhost >> /etc/hosts'], privileged=True, user='root') + node4.exec_in_container(['bash', '-c', 'echo 127.255.255.255 lost_host >> /etc/hosts'], privileged=True, user='root') + + with pytest.raises(QueryRuntimeException): + node4.query("SELECT * FROM remote('lost_host', 'system', 'one')") + + node4.query("CREATE TABLE distributed_lost_host (dummy UInt8) ENGINE = Distributed(lost_host_cluster, 'system', 'one')") + with pytest.raises(QueryRuntimeException): + node4.query("SELECT * FROM distributed_lost_host") + + node4.exec_in_container(['bash', '-c', 'echo 127.0.0.1 localhost > /etc/hosts'], privileged=True, user='root') + node4.exec_in_container(['bash', '-c', 'echo ::1 localhost >> /etc/hosts'], privileged=True, user='root') + node4.exec_in_container(['bash', '-c', 'echo 127.0.0.1 lost_host >> /etc/hosts'], privileged=True, user='root') + + # Wait a bit until dns cache will be updated + assert_eq_with_retry(node4, "SELECT * FROM remote('lost_host', 'system', 'one')", "0") + assert_eq_with_retry(node4, "SELECT * FROM distributed_lost_host", "0") + + assert TSV(node4.query("SELECT DISTINCT host_name, host_address FROM system.clusters WHERE cluster='lost_host_cluster'")) == TSV("lost_host\t127.0.0.1\n") + assert TSV(node4.query("SELECT hostName()")) == TSV("node4") diff --git a/dbms/tests/integration/test_odbc_interaction/test.py b/dbms/tests/integration/test_odbc_interaction/test.py index a19c71944da..d65745aa496 100644 --- a/dbms/tests/integration/test_odbc_interaction/test.py +++ b/dbms/tests/integration/test_odbc_interaction/test.py @@ -191,18 +191,9 @@ def test_postgres_odbc_hached_dictionary_no_tty_pipe_overflow(started_cluster): def test_bridge_dies_with_parent(started_cluster): node1.query("select dictGetString('postgres_odbc_hashed', 'column2', toUInt64(1))") - def get_pid(cmd): - output = node1.exec_in_container(["bash", "-c", "ps ax | grep '{}' | grep -v 'grep' | grep -v 'bash -c' | awk '{{print $1}}'".format(cmd)], privileged=True, user='root') - if output: - try: - pid = int(output.split('\n')[0].strip()) - return pid - except: - return None - return None - clickhouse_pid = get_pid("clickhouse server") - bridge_pid = get_pid("odbc-bridge") + clickhouse_pid = node1.get_process_pid("clickhouse server") + bridge_pid = node1.get_process_pid("odbc-bridge") assert clickhouse_pid is not None assert bridge_pid is not None @@ -211,11 +202,11 @@ def test_bridge_dies_with_parent(started_cluster): node1.exec_in_container(["bash", "-c", "kill {}".format(clickhouse_pid)], privileged=True, user='root') except: pass - clickhouse_pid = get_pid("clickhouse server") + clickhouse_pid = node1.get_process_pid("clickhouse server") time.sleep(1) time.sleep(1) # just for sure, that odbc-bridge caught signal - bridge_pid = get_pid("odbc-bridge") + bridge_pid = node1.get_process_pid("odbc-bridge") assert clickhouse_pid is None assert bridge_pid is None diff --git a/dbms/tests/integration/test_old_versions_client/__init__.py b/dbms/tests/integration/test_old_versions_client/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dbms/tests/integration/test_old_versions_client/test.py b/dbms/tests/integration/test_old_versions_client/test.py new file mode 100644 index 00000000000..2977d82ee9a --- /dev/null +++ b/dbms/tests/integration/test_old_versions_client/test.py @@ -0,0 +1,50 @@ +import time +import pytest + +from helpers.cluster import ClickHouseCluster +from multiprocessing.dummy import Pool +from helpers.client import QueryRuntimeException, QueryTimeoutExceedException + +from helpers.test_tools import assert_eq_with_retry +cluster = ClickHouseCluster(__file__) +node18_14 = cluster.add_instance('node18_14', image='yandex/clickhouse-server:18.14.19', with_installed_binary=True) +node19_1 = cluster.add_instance('node19_1', image='yandex/clickhouse-server:19.1.16', with_installed_binary=True) +node19_4 = cluster.add_instance('node19_4', image='yandex/clickhouse-server:19.4.5.35', with_installed_binary=True) +node19_6 = cluster.add_instance('node19_6', image='yandex/clickhouse-server:19.6.3.18', with_installed_binary=True) +node_new = cluster.add_instance('node_new') + +@pytest.fixture(scope="module") +def setup_nodes(): + try: + cluster.start() + for n in (node18_14, node19_1, node19_4, node19_6, node_new): + n.query('''CREATE TABLE test_table (id UInt32, value UInt64) ENGINE = MergeTree() ORDER BY tuple()''') + + yield cluster + finally: + cluster.shutdown() + + +def query_from_one_node_to_another(client_node, server_node, query): + client_node.exec_in_container(["bash", "-c", "/usr/bin/clickhouse client --host {} --query '{}'".format(server_node.name, query)]) + +def test_client_from_different_versions(setup_nodes): + old_nodes = (node18_14, node19_1, node19_4, node19_6,) + # from new to old + for n in old_nodes: + query_from_one_node_to_another(node_new, n, "INSERT INTO test_table VALUES (1, 1)") + + for n in old_nodes: + query_from_one_node_to_another(node_new, n, "SELECT COUNT() FROM test_table") + + for n in old_nodes: + assert n.query("SELECT COUNT() FROM test_table") == "1\n" + + # from old to new + for i, n in enumerate(old_nodes): + query_from_one_node_to_another(n, node_new, "INSERT INTO test_table VALUES ({i}, {i})".format(i=i)) + + for n in old_nodes: + query_from_one_node_to_another(n, node_new, "SELECT COUNT() FROM test_table") + + assert node_new.query("SELECT COUNT() FROM test_table") == str(len(old_nodes)) + "\n" diff --git a/dbms/tests/integration/test_storage_kafka/test.py b/dbms/tests/integration/test_storage_kafka/test.py index 3e562fbbcbb..3f38b068a22 100644 --- a/dbms/tests/integration/test_storage_kafka/test.py +++ b/dbms/tests/integration/test_storage_kafka/test.py @@ -22,7 +22,6 @@ import kafka_pb2 # TODO: add test for run-time offset update in CH, if we manually update it on Kafka side. -# TODO: add test for mat. view is working. # TODO: add test for SELECT LIMIT is working. # TODO: modify tests to respect `skip_broken_messages` setting. @@ -86,8 +85,8 @@ def kafka_produce_protobuf_messages(topic, start_index, num_messages): # Since everything is async and shaky when receiving messages from Kafka, # we may want to try and check results multiple times in a loop. -def kafka_check_result(result, check=False): - fpath = p.join(p.dirname(__file__), 'test_kafka_json.reference') +def kafka_check_result(result, check=False, ref_file='test_kafka_json.reference'): + fpath = p.join(p.dirname(__file__), ref_file) with open(fpath) as reference: if check: assert TSV(result) == TSV(reference) @@ -148,13 +147,12 @@ def test_kafka_settings_new_syntax(kafka_cluster): instance.query(''' CREATE TABLE test.kafka (key UInt64, value UInt64) ENGINE = Kafka - SETTINGS - kafka_broker_list = 'kafka1:19092', - kafka_topic_list = 'new', - kafka_group_name = 'new', - kafka_format = 'JSONEachRow', - kafka_row_delimiter = '\\n', - kafka_skip_broken_messages = 1; + SETTINGS kafka_broker_list = 'kafka1:19092', + kafka_topic_list = 'new', + kafka_group_name = 'new', + kafka_format = 'JSONEachRow', + kafka_row_delimiter = '\\n', + kafka_skip_broken_messages = 1; ''') messages = [] @@ -172,7 +170,7 @@ def test_kafka_settings_new_syntax(kafka_cluster): kafka_produce('new', messages) result = '' - for i in range(50): + while True: result += instance.query('SELECT * FROM test.kafka') if kafka_check_result(result): break @@ -183,12 +181,11 @@ def test_kafka_csv_with_delimiter(kafka_cluster): instance.query(''' CREATE TABLE test.kafka (key UInt64, value UInt64) ENGINE = Kafka - SETTINGS - kafka_broker_list = 'kafka1:19092', - kafka_topic_list = 'csv', - kafka_group_name = 'csv', - kafka_format = 'CSV', - kafka_row_delimiter = '\\n'; + SETTINGS kafka_broker_list = 'kafka1:19092', + kafka_topic_list = 'csv', + kafka_group_name = 'csv', + kafka_format = 'CSV', + kafka_row_delimiter = '\\n'; ''') messages = [] @@ -197,7 +194,7 @@ def test_kafka_csv_with_delimiter(kafka_cluster): kafka_produce('csv', messages) result = '' - for i in range(50): + while True: result += instance.query('SELECT * FROM test.kafka') if kafka_check_result(result): break @@ -208,12 +205,11 @@ def test_kafka_tsv_with_delimiter(kafka_cluster): instance.query(''' CREATE TABLE test.kafka (key UInt64, value UInt64) ENGINE = Kafka - SETTINGS - kafka_broker_list = 'kafka1:19092', - kafka_topic_list = 'tsv', - kafka_group_name = 'tsv', - kafka_format = 'TSV', - kafka_row_delimiter = '\\n'; + SETTINGS kafka_broker_list = 'kafka1:19092', + kafka_topic_list = 'tsv', + kafka_group_name = 'tsv', + kafka_format = 'TSV', + kafka_row_delimiter = '\\n'; ''') messages = [] @@ -222,7 +218,7 @@ def test_kafka_tsv_with_delimiter(kafka_cluster): kafka_produce('tsv', messages) result = '' - for i in range(50): + while True: result += instance.query('SELECT * FROM test.kafka') if kafka_check_result(result): break @@ -233,11 +229,10 @@ def test_kafka_json_without_delimiter(kafka_cluster): instance.query(''' CREATE TABLE test.kafka (key UInt64, value UInt64) ENGINE = Kafka - SETTINGS - kafka_broker_list = 'kafka1:19092', - kafka_topic_list = 'json', - kafka_group_name = 'json', - kafka_format = 'JSONEachRow'; + SETTINGS kafka_broker_list = 'kafka1:19092', + kafka_topic_list = 'json', + kafka_group_name = 'json', + kafka_format = 'JSONEachRow'; ''') messages = '' @@ -251,7 +246,7 @@ def test_kafka_json_without_delimiter(kafka_cluster): kafka_produce('json', [messages]) result = '' - for i in range(50): + while True: result += instance.query('SELECT * FROM test.kafka') if kafka_check_result(result): break @@ -262,12 +257,11 @@ def test_kafka_protobuf(kafka_cluster): instance.query(''' CREATE TABLE test.kafka (key UInt64, value String) ENGINE = Kafka - SETTINGS - kafka_broker_list = 'kafka1:19092', - kafka_topic_list = 'pb', - kafka_group_name = 'pb', - kafka_format = 'Protobuf', - kafka_schema = 'kafka.proto:KeyValuePair'; + SETTINGS kafka_broker_list = 'kafka1:19092', + kafka_topic_list = 'pb', + kafka_group_name = 'pb', + kafka_format = 'Protobuf', + kafka_schema = 'kafka.proto:KeyValuePair'; ''') kafka_produce_protobuf_messages('pb', 0, 20) @@ -275,7 +269,7 @@ def test_kafka_protobuf(kafka_cluster): kafka_produce_protobuf_messages('pb', 21, 29) result = '' - for i in range(50): + while True: result += instance.query('SELECT * FROM test.kafka') if kafka_check_result(result): break @@ -288,12 +282,11 @@ def test_kafka_materialized_view(kafka_cluster): DROP TABLE IF EXISTS test.consumer; CREATE TABLE test.kafka (key UInt64, value UInt64) ENGINE = Kafka - SETTINGS - kafka_broker_list = 'kafka1:19092', - kafka_topic_list = 'json', - kafka_group_name = 'json', - kafka_format = 'JSONEachRow', - kafka_row_delimiter = '\\n'; + SETTINGS kafka_broker_list = 'kafka1:19092', + kafka_topic_list = 'mv', + kafka_group_name = 'mv', + kafka_format = 'JSONEachRow', + kafka_row_delimiter = '\\n'; CREATE TABLE test.view (key UInt64, value UInt64) ENGINE = MergeTree() ORDER BY key; @@ -304,9 +297,9 @@ def test_kafka_materialized_view(kafka_cluster): messages = [] for i in range(50): messages.append(json.dumps({'key': i, 'value': i})) - kafka_produce('json', messages) + kafka_produce('mv', messages) - for i in range(20): + while True: time.sleep(1) result = instance.query('SELECT * FROM test.view') if kafka_check_result(result): @@ -321,7 +314,7 @@ def test_kafka_materialized_view(kafka_cluster): @pytest.mark.skip(reason="Hungs") def test_kafka_flush_on_big_message(kafka_cluster): # Create batchs of messages of size ~100Kb - kafka_messages = 10000 + kafka_messages = 1000 batch_messages = 1000 messages = [json.dumps({'key': i, 'value': 'x' * 100}) * batch_messages for i in range(kafka_messages)] kafka_produce('flush', messages) @@ -331,12 +324,11 @@ def test_kafka_flush_on_big_message(kafka_cluster): DROP TABLE IF EXISTS test.consumer; CREATE TABLE test.kafka (key UInt64, value String) ENGINE = Kafka - SETTINGS - kafka_broker_list = 'kafka1:19092', - kafka_topic_list = 'flush', - kafka_group_name = 'flush', - kafka_format = 'JSONEachRow', - kafka_max_block_size = 10; + SETTINGS kafka_broker_list = 'kafka1:19092', + kafka_topic_list = 'flush', + kafka_group_name = 'flush', + kafka_format = 'JSONEachRow', + kafka_max_block_size = 10; CREATE TABLE test.view (key UInt64, value String) ENGINE = MergeTree ORDER BY key; @@ -356,7 +348,7 @@ def test_kafka_flush_on_big_message(kafka_cluster): except kafka.errors.GroupCoordinatorNotAvailableError: continue - for _ in range(20): + while True: time.sleep(1) result = instance.query('SELECT count() FROM test.view') if int(result) == kafka_messages*batch_messages: @@ -365,6 +357,71 @@ def test_kafka_flush_on_big_message(kafka_cluster): assert int(result) == kafka_messages*batch_messages, 'ClickHouse lost some messages: {}'.format(result) +def test_kafka_virtual_columns(kafka_cluster): + instance.query(''' + CREATE TABLE test.kafka (key UInt64, value UInt64) + ENGINE = Kafka + SETTINGS kafka_broker_list = 'kafka1:19092', + kafka_topic_list = 'virt1', + kafka_group_name = 'virt1', + kafka_format = 'JSONEachRow'; + ''') + + messages = '' + for i in range(25): + messages += json.dumps({'key': i, 'value': i}) + '\n' + kafka_produce('virt1', [messages]) + + messages = '' + for i in range(25, 50): + messages += json.dumps({'key': i, 'value': i}) + '\n' + kafka_produce('virt1', [messages]) + + result = '' + while True: + time.sleep(1) + result += instance.query('SELECT _key, key, _topic, value, _offset FROM test.kafka') + if kafka_check_result(result, False, 'test_kafka_virtual1.reference'): + break + kafka_check_result(result, True, 'test_kafka_virtual1.reference') + + +def test_kafka_virtual_columns_with_materialized_view(kafka_cluster): + instance.query(''' + DROP TABLE IF EXISTS test.view; + DROP TABLE IF EXISTS test.consumer; + CREATE TABLE test.kafka (key UInt64, value UInt64) + ENGINE = Kafka + SETTINGS kafka_broker_list = 'kafka1:19092', + kafka_topic_list = 'virt2', + kafka_group_name = 'virt2', + kafka_format = 'JSONEachRow', + kafka_row_delimiter = '\\n'; + CREATE TABLE test.view (key UInt64, value UInt64, kafka_key String, topic String, offset UInt64) + ENGINE = MergeTree() + ORDER BY key; + CREATE MATERIALIZED VIEW test.consumer TO test.view AS + SELECT *, _key as kafka_key, _topic as topic, _offset as offset FROM test.kafka; + ''') + + messages = [] + for i in range(50): + messages.append(json.dumps({'key': i, 'value': i})) + kafka_produce('virt2', messages) + + while True: + time.sleep(1) + result = instance.query('SELECT kafka_key, key, topic, value, offset FROM test.view') + if kafka_check_result(result, False, 'test_kafka_virtual2.reference'): + break + kafka_check_result(result, True, 'test_kafka_virtual2.reference') + + instance.query(''' + DROP TABLE test.consumer; + DROP TABLE test.view; + ''') + + if __name__ == '__main__': cluster.start() raw_input("Cluster created, press any key to destroy...") diff --git a/dbms/tests/integration/test_storage_kafka/test_kafka_virtual1.reference b/dbms/tests/integration/test_storage_kafka/test_kafka_virtual1.reference new file mode 100644 index 00000000000..5956210d25e --- /dev/null +++ b/dbms/tests/integration/test_storage_kafka/test_kafka_virtual1.reference @@ -0,0 +1,50 @@ + 0 virt1 0 0 + 1 virt1 1 0 + 2 virt1 2 0 + 3 virt1 3 0 + 4 virt1 4 0 + 5 virt1 5 0 + 6 virt1 6 0 + 7 virt1 7 0 + 8 virt1 8 0 + 9 virt1 9 0 + 10 virt1 10 0 + 11 virt1 11 0 + 12 virt1 12 0 + 13 virt1 13 0 + 14 virt1 14 0 + 15 virt1 15 0 + 16 virt1 16 0 + 17 virt1 17 0 + 18 virt1 18 0 + 19 virt1 19 0 + 20 virt1 20 0 + 21 virt1 21 0 + 22 virt1 22 0 + 23 virt1 23 0 + 24 virt1 24 0 + 25 virt1 25 1 + 26 virt1 26 1 + 27 virt1 27 1 + 28 virt1 28 1 + 29 virt1 29 1 + 30 virt1 30 1 + 31 virt1 31 1 + 32 virt1 32 1 + 33 virt1 33 1 + 34 virt1 34 1 + 35 virt1 35 1 + 36 virt1 36 1 + 37 virt1 37 1 + 38 virt1 38 1 + 39 virt1 39 1 + 40 virt1 40 1 + 41 virt1 41 1 + 42 virt1 42 1 + 43 virt1 43 1 + 44 virt1 44 1 + 45 virt1 45 1 + 46 virt1 46 1 + 47 virt1 47 1 + 48 virt1 48 1 + 49 virt1 49 1 diff --git a/dbms/tests/integration/test_storage_kafka/test_kafka_virtual2.reference b/dbms/tests/integration/test_storage_kafka/test_kafka_virtual2.reference new file mode 100644 index 00000000000..50c2edbf802 --- /dev/null +++ b/dbms/tests/integration/test_storage_kafka/test_kafka_virtual2.reference @@ -0,0 +1,50 @@ + 0 virt2 0 0 + 1 virt2 1 1 + 2 virt2 2 2 + 3 virt2 3 3 + 4 virt2 4 4 + 5 virt2 5 5 + 6 virt2 6 6 + 7 virt2 7 7 + 8 virt2 8 8 + 9 virt2 9 9 + 10 virt2 10 10 + 11 virt2 11 11 + 12 virt2 12 12 + 13 virt2 13 13 + 14 virt2 14 14 + 15 virt2 15 15 + 16 virt2 16 16 + 17 virt2 17 17 + 18 virt2 18 18 + 19 virt2 19 19 + 20 virt2 20 20 + 21 virt2 21 21 + 22 virt2 22 22 + 23 virt2 23 23 + 24 virt2 24 24 + 25 virt2 25 25 + 26 virt2 26 26 + 27 virt2 27 27 + 28 virt2 28 28 + 29 virt2 29 29 + 30 virt2 30 30 + 31 virt2 31 31 + 32 virt2 32 32 + 33 virt2 33 33 + 34 virt2 34 34 + 35 virt2 35 35 + 36 virt2 36 36 + 37 virt2 37 37 + 38 virt2 38 38 + 39 virt2 39 39 + 40 virt2 40 40 + 41 virt2 41 41 + 42 virt2 42 42 + 43 virt2 43 43 + 44 virt2 44 44 + 45 virt2 45 45 + 46 virt2 46 46 + 47 virt2 47 47 + 48 virt2 48 48 + 49 virt2 49 49 diff --git a/dbms/tests/integration/test_system_queries/configs/config.d/query_log.xml b/dbms/tests/integration/test_system_queries/configs/config.d/query_log.xml new file mode 100644 index 00000000000..9f55dcb829e --- /dev/null +++ b/dbms/tests/integration/test_system_queries/configs/config.d/query_log.xml @@ -0,0 +1,9 @@ + + + + system + query_log
+ toYYYYMM(event_date) + 300 +
+
diff --git a/dbms/tests/integration/test_system_queries/test.py b/dbms/tests/integration/test_system_queries/test.py index a3899bab577..1761017362a 100644 --- a/dbms/tests/integration/test_system_queries/test.py +++ b/dbms/tests/integration/test_system_queries/test.py @@ -92,6 +92,23 @@ def test_RELOAD_CONFIG_AND_MACROS(started_cluster): instance.query("SYSTEM RELOAD CONFIG") assert TSV(instance.query("select * from system.macros")) == TSV("mac\tro\n") + +def test_SYSTEM_FLUSH_LOGS(started_cluster): + instance = cluster.instances['ch1'] + for i in range(4): + # Sleep to execute flushing from background thread at first query + # by expiration of flush_interval_millisecond and test probable race condition. + time.sleep(0.5) + result = instance.query(''' + SET log_queries = 1; + SELECT 1 FORMAT Null; + SET log_queries = 0; + SYSTEM FLUSH LOGS; + SELECT count() FROM system.query_log;''') + instance.query('TRUNCATE TABLE system.query_log') + assert TSV(result) == TSV('4') + + if __name__ == '__main__': with contextmanager(started_cluster)() as cluster: for name, instance in cluster.instances.items(): diff --git a/dbms/tests/performance/h3.xml b/dbms/tests/performance/h3.xml new file mode 100644 index 00000000000..7381f559a0f --- /dev/null +++ b/dbms/tests/performance/h3.xml @@ -0,0 +1,14 @@ + + once + + + + + 2000 + 10000 + + + + + SELECT count() FROM system.numbers WHERE NOT ignore(geoToH3(37.62 + rand(1) / 0x100000000, 55.75 + rand(2) / 0x100000000, 15)) + diff --git a/dbms/tests/performance/jit_large_requests.xml b/dbms/tests/performance/jit_large_requests.xml new file mode 100644 index 00000000000..54aa2af65b1 --- /dev/null +++ b/dbms/tests/performance/jit_large_requests.xml @@ -0,0 +1,64 @@ + + loop + + + + 100 + + + + + CREATE TABLE jit_test ( + a UInt64, + b UInt64, + c UInt64, + d UInt64, + e UInt64, + f UInt64, + g UInt64, + h UInt64, + i UInt64, + j UInt64 + ) Engine = Memory + + + + INSERT INTO jit_test + SELECT + number, + number, + number, + number, + number, + number, + number, + number, + number, + number + FROM + system.numbers + LIMIT 10000000 + + + SELECT + COUNT() + FROM + jit_test + WHERE + NOT ignore(a / b + c / d + e / f + g / h + i / j) + SETTINGS + compile_expressions = 0; + + + SELECT + COUNT() + FROM + jit_test + WHERE + NOT ignore(a / b + c / d + e / f + g / h + i / j) + SETTINGS + compile_expressions = 1, + min_count_to_compile = 1 + + DROP TABLE IF EXISTS jit_test + diff --git a/dbms/tests/performance/small_requests.xml b/dbms/tests/performance/jit_small_requests.xml similarity index 100% rename from dbms/tests/performance/small_requests.xml rename to dbms/tests/performance/jit_small_requests.xml diff --git a/dbms/tests/performance/merge_table_streams.xml b/dbms/tests/performance/merge_table_streams.xml new file mode 100644 index 00000000000..3f19c21109e --- /dev/null +++ b/dbms/tests/performance/merge_table_streams.xml @@ -0,0 +1,42 @@ + + loop + + + hits_100m_single + + + + + 60000 + 3 + + + 30 + + + + + + + + + 5 + + + +CREATE TABLE merge_table_streams_1 AS hits_100m_single +CREATE TABLE merge_table_streams_2 AS hits_100m_single +CREATE TABLE merge_table_streams_3 AS hits_100m_single +CREATE TABLE merge_table_streams_4 AS hits_100m_single + +SELECT UserID FROM merge(default, '^(hits_100m_single|merge_table_streams_\\d)$') WHERE UserID = 12345678901234567890 + +DROP TABLE merge_table_streams_1 +DROP TABLE merge_table_streams_2 +DROP TABLE merge_table_streams_3 +DROP TABLE merge_table_streams_4 + + diff --git a/dbms/tests/queries/0_stateless/00063_check_query.reference b/dbms/tests/queries/0_stateless/00063_check_query.reference index 6ed281c757a..9b20cc02e31 100644 --- a/dbms/tests/queries/0_stateless/00063_check_query.reference +++ b/dbms/tests/queries/0_stateless/00063_check_query.reference @@ -1,2 +1,5 @@ -1 -1 +N.bin 1 +S.bin 1 +N.bin 1 +S.bin 1 +__marks.mrk 1 diff --git a/dbms/tests/queries/0_stateless/00080_show_tables_and_system_tables.sql b/dbms/tests/queries/0_stateless/00080_show_tables_and_system_tables.sql index d3295f086e8..88facac19e1 100644 --- a/dbms/tests/queries/0_stateless/00080_show_tables_and_system_tables.sql +++ b/dbms/tests/queries/0_stateless/00080_show_tables_and_system_tables.sql @@ -24,11 +24,6 @@ DROP DATABASE IF EXISTS test_DatabaseMemory; CREATE DATABASE test_DatabaseMemory ENGINE = Memory; CREATE TABLE test_DatabaseMemory.A (A UInt8) ENGINE = Null; --- Just in case -DROP DATABASE IF EXISTS test_DatabaseDictionary; -CREATE DATABASE test_DatabaseDictionary ENGINE = Dictionary; - SELECT sum(ignore(*, metadata_modification_time, engine_full, create_table_query)) FROM system.tables; -DROP DATABASE test_DatabaseDictionary; -- { serverError 48 } DROP DATABASE test_DatabaseMemory; diff --git a/dbms/tests/queries/0_stateless/00110_external_sort.sql b/dbms/tests/queries/0_stateless/00110_external_sort.sql index 91459d2dabb..e7d6b41837b 100644 --- a/dbms/tests/queries/0_stateless/00110_external_sort.sql +++ b/dbms/tests/queries/0_stateless/00110_external_sort.sql @@ -1,3 +1,3 @@ -SET max_memory_usage = 100000000; +SET max_memory_usage = 300000000; SET max_bytes_before_external_sort = 20000000; SELECT number FROM (SELECT number FROM system.numbers LIMIT 10000000) ORDER BY number * 1234567890123456789 LIMIT 9999990, 10; diff --git a/dbms/tests/queries/0_stateless/00111_shard_external_sort_distributed.sql b/dbms/tests/queries/0_stateless/00111_shard_external_sort_distributed.sql index 676be19852b..5f5fa5443fd 100644 --- a/dbms/tests/queries/0_stateless/00111_shard_external_sort_distributed.sql +++ b/dbms/tests/queries/0_stateless/00111_shard_external_sort_distributed.sql @@ -1,4 +1,4 @@ -SET max_memory_usage = 100000000; +SET max_memory_usage = 300000000; SET max_bytes_before_external_sort = 20000000; DROP TABLE IF EXISTS numbers10m; diff --git a/dbms/tests/queries/0_stateless/00153_transform.sql b/dbms/tests/queries/0_stateless/00153_transform.sql index a5b79eeecec..a5e531d36a4 100644 --- a/dbms/tests/queries/0_stateless/00153_transform.sql +++ b/dbms/tests/queries/0_stateless/00153_transform.sql @@ -12,3 +12,7 @@ SELECT transform(1, [2, 3], ['Яндекс', 'Google'], 'Остальные') AS SELECT transform(2, [2, 3], ['Яндекс', 'Google'], 'Остальные') AS title; SELECT transform(3, [2, 3], ['Яндекс', 'Google'], 'Остальные') AS title; SELECT transform(4, [2, 3], ['Яндекс', 'Google'], 'Остальные') AS title; +SELECT transform('hello', 'wrong', 1); -- { serverError 43 } +SELECT transform('hello', ['wrong'], 1); -- { serverError 43 } +SELECT transform('hello', ['wrong'], [1]); -- { serverError 43 } +SELECT transform(tuple(1), ['sdf'], [1]); -- { serverError 43 } diff --git a/dbms/tests/queries/0_stateless/00254_tuple_extremes.sql b/dbms/tests/queries/0_stateless/00254_tuple_extremes.sql index f87fdf93d3b..9c78463bc38 100644 --- a/dbms/tests/queries/0_stateless/00254_tuple_extremes.sql +++ b/dbms/tests/queries/0_stateless/00254_tuple_extremes.sql @@ -1 +1,8 @@ -SELECT number, (number, toDate('2015-01-01') + number) FROM system.numbers LIMIT 10 SETTINGS extremes = 1; +drop table if exists numbers_10; + +create table numbers_10 (number UInt64) engine = MergeTree order by number; +insert into numbers_10 select number from system.numbers limit 10; + +SELECT number, (number, toDate('2015-01-01') + number) FROM numbers_10 LIMIT 10 SETTINGS extremes = 1; + +drop table if exists numbers_10; diff --git a/dbms/tests/queries/0_stateless/00336_shard_stack_trace.sh b/dbms/tests/queries/0_stateless/00336_shard_stack_trace.sh index f2a2556d328..a7f25be52be 100755 --- a/dbms/tests/queries/0_stateless/00336_shard_stack_trace.sh +++ b/dbms/tests/queries/0_stateless/00336_shard_stack_trace.sh @@ -5,9 +5,9 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d 'SELECT a' | wc -l ${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}?stacktrace=0" -d 'SELECT a' | wc -l -[[ $(${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}?stacktrace=1" -d 'SELECT a' | wc -l) -gt 3 ]] && echo 'Ok' || echo 'Fail' +[[ $(${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}?stacktrace=1" -d 'SELECT a' | wc -l) -ge 3 ]] && echo 'Ok' || echo 'Fail' ${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d "SELECT intDiv(number, 0) FROM remote('127.0.0.{2,3}', system.numbers)" | wc -l $CLICKHOUSE_CLIENT --query="SELECT a" --server_logs_file=/dev/null 2>&1 | wc -l -[[ $($CLICKHOUSE_CLIENT --query="SELECT a" --server_logs_file=/dev/null --stacktrace 2>&1 | wc -l) -gt 3 ]] && echo 'Ok' || echo 'Fail' +[[ $($CLICKHOUSE_CLIENT --query="SELECT a" --server_logs_file=/dev/null --stacktrace 2>&1 | wc -l) -ge 3 ]] && echo 'Ok' || echo 'Fail' $CLICKHOUSE_CLIENT --query="SELECT intDiv(number, 0) FROM remote('127.0.0.{2,3}', system.numbers)" --server_logs_file=/dev/null 2>&1 | wc -l diff --git a/dbms/tests/queries/0_stateless/00365_statistics_in_formats.sh b/dbms/tests/queries/0_stateless/00365_statistics_in_formats.sh index 202611821de..f0e23337806 100755 --- a/dbms/tests/queries/0_stateless/00365_statistics_in_formats.sh +++ b/dbms/tests/queries/0_stateless/00365_statistics_in_formats.sh @@ -3,10 +3,16 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) . $CURDIR/../shell_config.sh -$CLICKHOUSE_CLIENT --query="SELECT number FROM system.numbers LIMIT 10 FORMAT JSON" | grep 'rows_read'; -$CLICKHOUSE_CLIENT --query="SELECT number FROM system.numbers LIMIT 10 FORMAT JSONCompact" | grep 'rows_read'; -$CLICKHOUSE_CLIENT --query="SELECT number FROM system.numbers LIMIT 10 FORMAT XML" | grep 'rows_read'; +$CLICKHOUSE_CLIENT --query="DROP TABLE IF EXISTS test.numbers"; +$CLICKHOUSE_CLIENT --query="CREATE TABLE test.numbers (number UInt64) engine = MergeTree order by number"; +$CLICKHOUSE_CLIENT --query="INSERT INTO test.numbers select * from system.numbers limit 10"; -${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d "SELECT number FROM system.numbers LIMIT 10 FORMAT JSON" | grep 'rows_read'; -${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d "SELECT number FROM system.numbers LIMIT 10 FORMAT JSONCompact" | grep 'rows_read'; -${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d "SELECT number FROM system.numbers LIMIT 10 FORMAT XML" | grep 'rows_read'; +$CLICKHOUSE_CLIENT --query="SELECT number FROM test.numbers LIMIT 10 FORMAT JSON" | grep 'rows_read'; +$CLICKHOUSE_CLIENT --query="SELECT number FROM test.numbers LIMIT 10 FORMAT JSONCompact" | grep 'rows_read'; +$CLICKHOUSE_CLIENT --query="SELECT number FROM test.numbers LIMIT 10 FORMAT XML" | grep 'rows_read'; + +${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d "SELECT number FROM test.numbers LIMIT 10 FORMAT JSON" | grep 'rows_read'; +${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d "SELECT number FROM test.numbers LIMIT 10 FORMAT JSONCompact" | grep 'rows_read'; +${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d "SELECT number FROM test.numbers LIMIT 10 FORMAT XML" | grep 'rows_read'; + +$CLICKHOUSE_CLIENT --query="DROP TABLE IF EXISTS test.numbers"; \ No newline at end of file diff --git a/dbms/tests/queries/0_stateless/00381_first_significant_subdomain.reference b/dbms/tests/queries/0_stateless/00381_first_significant_subdomain.reference index f13e9ddb1bd..1f1230a2104 100644 --- a/dbms/tests/queries/0_stateless/00381_first_significant_subdomain.reference +++ b/dbms/tests/queries/0_stateless/00381_first_significant_subdomain.reference @@ -1,3 +1,3 @@ canada congo net-domena yandex yandex yandex яндекс yandex -canada hello hello hello hello hello canada canada +canada hello hello canada diff --git a/dbms/tests/queries/0_stateless/00398_url_functions.reference b/dbms/tests/queries/0_stateless/00398_url_functions.reference index e4a31f0654a..acb605597d3 100644 --- a/dbms/tests/queries/0_stateless/00398_url_functions.reference +++ b/dbms/tests/queries/0_stateless/00398_url_functions.reference @@ -12,13 +12,17 @@ www.example.com 127.0.0.1 www.example.com www.example.com +www.example.com +example.com example.com example.com ====DOMAIN==== com ru -ru + +com +com com ====PATH==== П @@ -61,6 +65,8 @@ example.com example.com example.com example.com +example.com +example.com ====CUT WWW==== http://example.com http://example.com:1234 diff --git a/dbms/tests/queries/0_stateless/00398_url_functions.sql b/dbms/tests/queries/0_stateless/00398_url_functions.sql index 16425dae46d..d301cac5b15 100644 --- a/dbms/tests/queries/0_stateless/00398_url_functions.sql +++ b/dbms/tests/queries/0_stateless/00398_url_functions.sql @@ -13,6 +13,8 @@ SELECT domain('http://www.example.com?q=4') AS Host; SELECT domain('http://127.0.0.1:443/') AS Host; SELECT domain('//www.example.com') AS Host; SELECT domain('//paul@www.example.com') AS Host; +SELECT domain('www.example.com') as Host; +SELECT domain('example.com') as Host; SELECT domainWithoutWWW('//paul@www.example.com') AS Host; SELECT domainWithoutWWW('http://paul@www.example.com:80/') AS Host; @@ -23,6 +25,8 @@ SELECT topLevelDomain('http://127.0.0.1:443/') AS Domain; SELECT topLevelDomain('svn+ssh://example.ru?q=hello%20world') AS Domain; SELECT topLevelDomain('svn+ssh://example.ru.?q=hello%20world') AS Domain; SELECT topLevelDomain('//www.example.com') AS Domain; +SELECT topLevelDomain('www.example.com') as Domain; +SELECT topLevelDomain('example.com') as Domain; SELECT '====PATH===='; SELECT decodeURLComponent('%D0%9F'); @@ -69,6 +73,8 @@ SELECT cutToFirstSignificantSubdomain('http://www.example.com/a/b/c?a=b'); SELECT cutToFirstSignificantSubdomain('http://www.example.com/a/b/c?a=b#d=f'); SELECT cutToFirstSignificantSubdomain('http://paul@www.example.com/a/b/c?a=b#d=f'); SELECT cutToFirstSignificantSubdomain('//paul@www.example.com/a/b/c?a=b#d=f'); +SELECT cutToFirstSignificantSubdomain('www.example.com'); +SELECT cutToFirstSignificantSubdomain('example.com'); SELECT '====CUT WWW===='; SELECT cutWWW('http://www.example.com'); diff --git a/dbms/tests/queries/0_stateless/00416_pocopatch_progress_in_http_headers.sh b/dbms/tests/queries/0_stateless/00416_pocopatch_progress_in_http_headers.sh index 76ca56efca8..2ae5d905fbe 100755 --- a/dbms/tests/queries/0_stateless/00416_pocopatch_progress_in_http_headers.sh +++ b/dbms/tests/queries/0_stateless/00416_pocopatch_progress_in_http_headers.sh @@ -6,8 +6,9 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ${CLICKHOUSE_CURL} -vsS "${CLICKHOUSE_URL}?max_block_size=5&send_progress_in_http_headers=1&http_headers_progress_interval_ms=0" -d 'SELECT max(number) FROM numbers(10)' 2>&1 | grep -E 'Content-Encoding|X-ClickHouse-Progress|^[0-9]' # This test will fail with external poco (progress not supported) -${CLICKHOUSE_CURL} -vsS "${CLICKHOUSE_URL}?max_block_size=1&send_progress_in_http_headers=1&http_headers_progress_interval_ms=0" -d 'SELECT number FROM system.numbers LIMIT 10' 2>&1 | grep -E 'Content-Encoding|X-ClickHouse-Progress|^[0-9]' -${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}?max_block_size=1&send_progress_in_http_headers=1&http_headers_progress_interval_ms=0&enable_http_compression=1" -H 'Accept-Encoding: gzip' -d 'SELECT number FROM system.numbers LIMIT 10' | gzip -d +# "grep -v 11" in order to skip extra progress header for 11-th row (for processors pipeline) +${CLICKHOUSE_CURL} -vsS "${CLICKHOUSE_URL}?max_block_size=1&send_progress_in_http_headers=1&http_headers_progress_interval_ms=0&experimental_use_processors=0" -d 'SELECT number FROM system.numbers LIMIT 10' 2>&1 | grep -E 'Content-Encoding|X-ClickHouse-Progress|^[0-9]' | grep -v 11 +${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}?max_block_size=1&send_progress_in_http_headers=1&http_headers_progress_interval_ms=0&enable_http_compression=1experimental_use_processors=0" -H 'Accept-Encoding: gzip' -d 'SELECT number FROM system.numbers LIMIT 10' | gzip -d # 'send_progress_in_http_headers' is false by default ${CLICKHOUSE_CURL} -vsS "${CLICKHOUSE_URL}?max_block_size=1&http_headers_progress_interval_ms=0" -d 'SELECT number FROM system.numbers LIMIT 10' 2>&1 | grep -q 'X-ClickHouse-Progress' && echo 'Fail' || true diff --git a/dbms/tests/queries/0_stateless/00428_partition.reference b/dbms/tests/queries/0_stateless/00428_partition.reference index 07ae09cf47d..c777fd7a5c3 100644 --- a/dbms/tests/queries/0_stateless/00428_partition.reference +++ b/dbms/tests/queries/0_stateless/00428_partition.reference @@ -1,42 +1,54 @@ 5 5 -082814b5aa5109160d5c0c5aff10d4df shadow/1/data/test/partition_428/19700102_19700102_2_2_0/k.bin -082814b5aa5109160d5c0c5aff10d4df shadow/1/data/test/partition_428/19700201_19700201_1_1_0/v1.bin -38e62ff37e1e5064e9a3f605dfe09d13 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/v1.bin -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/k.mrk -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/p.mrk -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/v1.mrk -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/k.mrk -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/p.mrk -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/v1.mrk -55a54008ad1ba589aa210d2629c1df41 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/primary.idx -77d5af402ada101574f4da114f242e02 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/columns.txt -77d5af402ada101574f4da114f242e02 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/columns.txt -88cdc31ded355e7572d68d8cde525d3a shadow/1/data/test/partition_428/19700201_19700201_1_1_0/p.bin -9e688c58a5487b8eaf69c9e1005ad0bf shadow/1/data/test/partition_428/19700102_19700102_2_2_0/primary.idx -b01e3d4df40467db3f1c2d029f59f6a2 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/checksums.txt -cfcb770c3ecd0990dcceb1bde129e6c6 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/p.bin -e2af3bef1fd129aea73a890ede1e7a30 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/k.bin -e6654eba9e88b001280d3bdd21ccc417 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/checksums.txt +082814b5aa5109160d5c0c5aff10d4df shadow/1/data/test/partition_428/19700102_2_2_0/k.bin +082814b5aa5109160d5c0c5aff10d4df shadow/1/data/test/partition_428/19700201_1_1_0/v1.bin +13cae8e658e0ca4f75c56b1fc424e150 shadow/1/data/test/partition_428/19700102_2_2_0/minmax_p.idx +25daad3d9e60b45043a70c4ab7d3b1c6 shadow/1/data/test/partition_428/19700102_2_2_0/partition.dat +3726312af62aec86b64a7708d5751787 shadow/1/data/test/partition_428/19700201_1_1_0/partition.dat +37855b06a39b79a67ea4e86e4a3299aa shadow/1/data/test/partition_428/19700102_2_2_0/checksums.txt +38e62ff37e1e5064e9a3f605dfe09d13 shadow/1/data/test/partition_428/19700102_2_2_0/v1.bin +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_2_2_0/k.mrk +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_2_2_0/p.mrk +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_2_2_0/v1.mrk +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_1_1_0/k.mrk +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_1_1_0/p.mrk +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_1_1_0/v1.mrk +55a54008ad1ba589aa210d2629c1df41 shadow/1/data/test/partition_428/19700201_1_1_0/primary.idx +5f087cb3e7071bf9407e095821e2af8f shadow/1/data/test/partition_428/19700201_1_1_0/checksums.txt +77d5af402ada101574f4da114f242e02 shadow/1/data/test/partition_428/19700102_2_2_0/columns.txt +77d5af402ada101574f4da114f242e02 shadow/1/data/test/partition_428/19700201_1_1_0/columns.txt +88cdc31ded355e7572d68d8cde525d3a shadow/1/data/test/partition_428/19700201_1_1_0/p.bin +9e688c58a5487b8eaf69c9e1005ad0bf shadow/1/data/test/partition_428/19700102_2_2_0/primary.idx +c4ca4238a0b923820dcc509a6f75849b shadow/1/data/test/partition_428/19700102_2_2_0/count.txt +c4ca4238a0b923820dcc509a6f75849b shadow/1/data/test/partition_428/19700201_1_1_0/count.txt +cfcb770c3ecd0990dcceb1bde129e6c6 shadow/1/data/test/partition_428/19700102_2_2_0/p.bin +e2af3bef1fd129aea73a890ede1e7a30 shadow/1/data/test/partition_428/19700201_1_1_0/k.bin +f2312862cc01adf34a93151377be2ddf shadow/1/data/test/partition_428/19700201_1_1_0/minmax_p.idx 5 5 -082814b5aa5109160d5c0c5aff10d4df shadow/1/data/test/partition_428/19700102_19700102_2_2_0/k.bin -082814b5aa5109160d5c0c5aff10d4df shadow/1/data/test/partition_428/19700201_19700201_1_1_0/v1.bin -38e62ff37e1e5064e9a3f605dfe09d13 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/v1.bin -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/k.mrk -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/p.mrk -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/v1.mrk -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/k.mrk -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/p.mrk -4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/v1.mrk -55a54008ad1ba589aa210d2629c1df41 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/primary.idx -77d5af402ada101574f4da114f242e02 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/columns.txt -77d5af402ada101574f4da114f242e02 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/columns.txt -88cdc31ded355e7572d68d8cde525d3a shadow/1/data/test/partition_428/19700201_19700201_1_1_0/p.bin -9e688c58a5487b8eaf69c9e1005ad0bf shadow/1/data/test/partition_428/19700102_19700102_2_2_0/primary.idx -b01e3d4df40467db3f1c2d029f59f6a2 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/checksums.txt -cfcb770c3ecd0990dcceb1bde129e6c6 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/p.bin -e2af3bef1fd129aea73a890ede1e7a30 shadow/1/data/test/partition_428/19700201_19700201_1_1_0/k.bin -e6654eba9e88b001280d3bdd21ccc417 shadow/1/data/test/partition_428/19700102_19700102_2_2_0/checksums.txt +082814b5aa5109160d5c0c5aff10d4df shadow/1/data/test/partition_428/19700102_2_2_0/k.bin +082814b5aa5109160d5c0c5aff10d4df shadow/1/data/test/partition_428/19700201_1_1_0/v1.bin +13cae8e658e0ca4f75c56b1fc424e150 shadow/1/data/test/partition_428/19700102_2_2_0/minmax_p.idx +25daad3d9e60b45043a70c4ab7d3b1c6 shadow/1/data/test/partition_428/19700102_2_2_0/partition.dat +3726312af62aec86b64a7708d5751787 shadow/1/data/test/partition_428/19700201_1_1_0/partition.dat +37855b06a39b79a67ea4e86e4a3299aa shadow/1/data/test/partition_428/19700102_2_2_0/checksums.txt +38e62ff37e1e5064e9a3f605dfe09d13 shadow/1/data/test/partition_428/19700102_2_2_0/v1.bin +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_2_2_0/k.mrk +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_2_2_0/p.mrk +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700102_2_2_0/v1.mrk +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_1_1_0/k.mrk +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_1_1_0/p.mrk +4ae71336e44bf9bf79d2752e234818a5 shadow/1/data/test/partition_428/19700201_1_1_0/v1.mrk +55a54008ad1ba589aa210d2629c1df41 shadow/1/data/test/partition_428/19700201_1_1_0/primary.idx +5f087cb3e7071bf9407e095821e2af8f shadow/1/data/test/partition_428/19700201_1_1_0/checksums.txt +77d5af402ada101574f4da114f242e02 shadow/1/data/test/partition_428/19700102_2_2_0/columns.txt +77d5af402ada101574f4da114f242e02 shadow/1/data/test/partition_428/19700201_1_1_0/columns.txt +88cdc31ded355e7572d68d8cde525d3a shadow/1/data/test/partition_428/19700201_1_1_0/p.bin +9e688c58a5487b8eaf69c9e1005ad0bf shadow/1/data/test/partition_428/19700102_2_2_0/primary.idx +c4ca4238a0b923820dcc509a6f75849b shadow/1/data/test/partition_428/19700102_2_2_0/count.txt +c4ca4238a0b923820dcc509a6f75849b shadow/1/data/test/partition_428/19700201_1_1_0/count.txt +cfcb770c3ecd0990dcceb1bde129e6c6 shadow/1/data/test/partition_428/19700102_2_2_0/p.bin +e2af3bef1fd129aea73a890ede1e7a30 shadow/1/data/test/partition_428/19700201_1_1_0/k.bin +f2312862cc01adf34a93151377be2ddf shadow/1/data/test/partition_428/19700201_1_1_0/minmax_p.idx 31,1,2 1,2,3 diff --git a/dbms/tests/queries/0_stateless/00428_partition.sh b/dbms/tests/queries/0_stateless/00428_partition.sh index b45e978d755..033d5e24c13 100755 --- a/dbms/tests/queries/0_stateless/00428_partition.sh +++ b/dbms/tests/queries/0_stateless/00428_partition.sh @@ -13,7 +13,7 @@ chl="$CLICKHOUSE_CLIENT -q" ch_dir=`${CLICKHOUSE_EXTRACT_CONFIG} -k path` $chl "DROP TABLE IF EXISTS test.partition_428" -$chl "CREATE TABLE test.partition_428 (p Date, k Int8, v1 Int8 MATERIALIZED k + 1) ENGINE = MergeTree(p, k, 1)" +$chl "CREATE TABLE test.partition_428 (p Date, k Int8, v1 Int8 MATERIALIZED k + 1) ENGINE = MergeTree PARTITION BY p ORDER BY k SETTINGS index_granularity=1, index_granularity_bytes=0" $chl "INSERT INTO test.partition_428 (p, k) VALUES(toDate(31), 1)" $chl "INSERT INTO test.partition_428 (p, k) VALUES(toDate(1), 2)" @@ -51,7 +51,7 @@ $chl "DROP TABLE test.partition_428" # Test 2. Simple test $chl "drop table if exists test.partition_428" -$chl "create table test.partition_428 (date MATERIALIZED toDate(0), x UInt64, sample_key MATERIALIZED intHash64(x)) ENGINE=MergeTree(date,sample_key,(date,x,sample_key),8192)" +$chl "create table test.partition_428 (date MATERIALIZED toDate(0), x UInt64, sample_key MATERIALIZED intHash64(x)) ENGINE=MergeTree PARTITION BY date SAMPLE BY sample_key ORDER BY (date,x,sample_key) SETTINGS index_granularity=8192, index_granularity_bytes=0" $chl "insert into test.partition_428 ( x ) VALUES ( now() )" $chl "insert into test.partition_428 ( x ) VALUES ( now()+1 )" $chl "alter table test.partition_428 detach partition 197001" diff --git a/dbms/tests/queries/0_stateless/00443_preferred_block_size_bytes.sh b/dbms/tests/queries/0_stateless/00443_preferred_block_size_bytes.sh index 4ab4aa18c18..4bf104a2d03 100755 --- a/dbms/tests/queries/0_stateless/00443_preferred_block_size_bytes.sh +++ b/dbms/tests/queries/0_stateless/00443_preferred_block_size_bytes.sh @@ -6,7 +6,7 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) . $CURDIR/../shell_config.sh $CLICKHOUSE_CLIENT -q "DROP TABLE IF EXISTS preferred_block_size_bytes" -$CLICKHOUSE_CLIENT -q "CREATE TABLE preferred_block_size_bytes (p Date, s String) ENGINE = MergeTree(p, p, 1)" +$CLICKHOUSE_CLIENT -q "CREATE TABLE preferred_block_size_bytes (p Date, s String) ENGINE = MergeTree PARTITION BY p ORDER BY p SETTINGS index_granularity=1, index_granularity_bytes=0" $CLICKHOUSE_CLIENT -q "INSERT INTO preferred_block_size_bytes (s) SELECT '16_bytes_-_-_-_' AS s FROM system.numbers LIMIT 10, 90" $CLICKHOUSE_CLIENT -q "OPTIMIZE TABLE preferred_block_size_bytes" $CLICKHOUSE_CLIENT --preferred_block_size_bytes=26 -q "SELECT DISTINCT blockSize(), ignore(p, s) FROM preferred_block_size_bytes" @@ -17,7 +17,7 @@ $CLICKHOUSE_CLIENT -q "DROP TABLE IF EXISTS preferred_block_size_bytes" # PREWHERE using empty column $CLICKHOUSE_CLIENT -q "DROP TABLE IF EXISTS pbs" -$CLICKHOUSE_CLIENT -q "CREATE TABLE pbs (p Date, i UInt64, sa Array(String)) ENGINE = MergeTree(p, p, 100)" +$CLICKHOUSE_CLIENT -q "CREATE TABLE pbs (p Date, i UInt64, sa Array(String)) ENGINE = MergeTree PARTITION BY p ORDER BY p SETTINGS index_granularity=100, index_granularity_bytes=0" $CLICKHOUSE_CLIENT -q "INSERT INTO pbs (p, i, sa) SELECT toDate(i % 30) AS p, number AS i, ['a'] AS sa FROM system.numbers LIMIT 1000" $CLICKHOUSE_CLIENT -q "ALTER TABLE pbs ADD COLUMN s UInt8 DEFAULT 0" $CLICKHOUSE_CLIENT --preferred_block_size_bytes=100000 -q "SELECT count() FROM pbs PREWHERE s = 0" @@ -28,7 +28,7 @@ $CLICKHOUSE_CLIENT -q "DROP TABLE pbs" # Nullable PREWHERE $CLICKHOUSE_CLIENT -q "DROP TABLE IF EXISTS nullable_prewhere" -$CLICKHOUSE_CLIENT -q "CREATE TABLE nullable_prewhere (p Date, f Nullable(UInt64), d UInt64) ENGINE = MergeTree(p, p, 8)" +$CLICKHOUSE_CLIENT -q "CREATE TABLE nullable_prewhere (p Date, f Nullable(UInt64), d UInt64) ENGINE = MergeTree PARTITION BY p ORDER BY p SETTINGS index_granularity=8, index_granularity_bytes=0" $CLICKHOUSE_CLIENT -q "INSERT INTO nullable_prewhere SELECT toDate(0) AS p, if(number % 2 = 0, CAST(number AS Nullable(UInt64)), CAST(NULL AS Nullable(UInt64))) AS f, number as d FROM system.numbers LIMIT 1001" $CLICKHOUSE_CLIENT -q "SELECT sum(d), sum(f), max(d) FROM nullable_prewhere PREWHERE NOT isNull(f)" $CLICKHOUSE_CLIENT -q "DROP TABLE IF EXISTS nullable_prewhere" diff --git a/dbms/tests/queries/0_stateless/00445_join_nullable_keys.reference b/dbms/tests/queries/0_stateless/00445_join_nullable_keys.reference index 20673c90278..f7675766dc9 100644 --- a/dbms/tests/queries/0_stateless/00445_join_nullable_keys.reference +++ b/dbms/tests/queries/0_stateless/00445_join_nullable_keys.reference @@ -21,3 +21,4 @@ 12 12 13 13 14 14 +\N 8 diff --git a/dbms/tests/queries/0_stateless/00584_view_union_all.sql b/dbms/tests/queries/0_stateless/00584_view_union_all.sql index 87242842b23..2e4d7ea66db 100644 --- a/dbms/tests/queries/0_stateless/00584_view_union_all.sql +++ b/dbms/tests/queries/0_stateless/00584_view_union_all.sql @@ -23,7 +23,7 @@ CREATE VIEW TestView AS FROM Test_00584 GROUP BY str; -SELECT * FROM TestView; +SELECT * FROM TestView ORDER BY key; DROP TABLE TestView; DROP TABLE Test_00584; diff --git a/dbms/tests/queries/0_stateless/00587_union_all_type_conversions.reference b/dbms/tests/queries/0_stateless/00587_union_all_type_conversions.reference index be82f93ae83..326729c6098 100644 --- a/dbms/tests/queries/0_stateless/00587_union_all_type_conversions.reference +++ b/dbms/tests/queries/0_stateless/00587_union_all_type_conversions.reference @@ -7,12 +7,12 @@ 1 Nullable(UInt8) \N Nullable(UInt8) 1 -\N 1 +\N 1 Nullable(Float64) 2 \N Nullable(Float64) 1 -1 -2 3 +2 +1 nan \N diff --git a/dbms/tests/queries/0_stateless/00587_union_all_type_conversions.sql b/dbms/tests/queries/0_stateless/00587_union_all_type_conversions.sql index ad7b0a81149..6bc6d98d171 100644 --- a/dbms/tests/queries/0_stateless/00587_union_all_type_conversions.sql +++ b/dbms/tests/queries/0_stateless/00587_union_all_type_conversions.sql @@ -1,12 +1,12 @@ SET max_threads = 1; -SELECT 1 UNION ALL SELECT -1; -SELECT x, toTypeName(x) FROM (SELECT 1 AS x UNION ALL SELECT -1); +SELECT * FROM (SELECT 1 as x UNION ALL SELECT -1) ORDER BY x DESC; +SELECT * FROM (SELECT x, toTypeName(x) FROM (SELECT 1 AS x UNION ALL SELECT -1)) ORDER BY x DESC; -SELECT 1 UNION ALL SELECT NULL; -SELECT x, toTypeName(x) FROM (SELECT 1 AS x UNION ALL SELECT NULL); +SELECT x FROM (SELECT 1 as x UNION ALL SELECT NULL) ORDER BY x DESC; +SELECT * FROM (SELECT x, toTypeName(x) FROM (SELECT 1 AS x UNION ALL SELECT NULL)) ORDER BY x DESC; -SELECT 1 AS x UNION ALL SELECT NULL UNION ALL SELECT 1.0; -SELECT x, toTypeName(x), count() FROM (SELECT 1 AS x UNION ALL SELECT NULL UNION ALL SELECT 1.0) GROUP BY x; +SELECT x FROM (SELECT 1 AS x UNION ALL SELECT NULL UNION ALL SELECT 1.0) ORDER BY x DESC; +SELECT * FROM (SELECT x, toTypeName(x), count() FROM (SELECT 1 AS x UNION ALL SELECT NULL UNION ALL SELECT 1.0) GROUP BY x) ORDER BY x DESC; -SELECT arrayJoin(x) AS res FROM (SELECT [1, 2, 3] AS x UNION ALL SELECT [nan, NULL]) ORDER BY res; +SELECT res FROM (SELECT arrayJoin(x) AS res FROM (SELECT [1, 2, 3] AS x UNION ALL SELECT [nan, NULL]) ORDER BY res) ORDER BY res DESC; diff --git a/dbms/tests/queries/0_stateless/00597_push_down_predicate.reference b/dbms/tests/queries/0_stateless/00597_push_down_predicate.reference index ee84060db57..c71e5c1cdd9 100644 --- a/dbms/tests/queries/0_stateless/00597_push_down_predicate.reference +++ b/dbms/tests/queries/0_stateless/00597_push_down_predicate.reference @@ -4,59 +4,59 @@ 1 2000-01-01 1 test string 1 1 -------Forbid push down------- -SELECT count()\nFROM \n(\n SELECT \n [number] AS a, \n [number * 2] AS b\n FROM system.numbers \n LIMIT 1\n) AS t \nARRAY JOIN \n a, \n b\nWHERE NOT ignore(a + b) +SELECT count()\nFROM \n(\n SELECT \n [number] AS a, \n [number * 2] AS b\n FROM system.numbers\n LIMIT 1\n) AS t\nARRAY JOIN \n a, \n b\nWHERE NOT ignore(a + b) 1 -SELECT \n a, \n b\nFROM \n(\n SELECT 1 AS a\n) \nANY LEFT JOIN \n(\n SELECT \n 1 AS a, \n 1 AS b\n) USING (a)\nWHERE b = 0 -SELECT \n a, \n b\nFROM \n(\n SELECT \n 1 AS a, \n 1 AS b\n) \nANY RIGHT JOIN \n(\n SELECT 1 AS a\n) USING (a)\nWHERE b = 0 -SELECT \n a, \n b\nFROM \n(\n SELECT 1 AS a\n) \nANY FULL OUTER JOIN \n(\n SELECT \n 1 AS a, \n 1 AS b\n) USING (a)\nWHERE b = 0 -SELECT \n a, \n b\nFROM \n(\n SELECT \n 1 AS a, \n 1 AS b\n) \nANY FULL OUTER JOIN \n(\n SELECT 1 AS a\n) USING (a)\nWHERE b = 0 +SELECT \n a, \n b\nFROM \n(\n SELECT 1 AS a\n)\nANY LEFT JOIN \n(\n SELECT \n 1 AS a, \n 1 AS b\n) USING (a)\nWHERE b = 0 +SELECT \n a, \n b\nFROM \n(\n SELECT \n 1 AS a, \n 1 AS b\n)\nANY RIGHT JOIN \n(\n SELECT 1 AS a\n) USING (a)\nWHERE b = 0 +SELECT \n a, \n b\nFROM \n(\n SELECT 1 AS a\n)\nANY FULL OUTER JOIN \n(\n SELECT \n 1 AS a, \n 1 AS b\n) USING (a)\nWHERE b = 0 +SELECT \n a, \n b\nFROM \n(\n SELECT \n 1 AS a, \n 1 AS b\n)\nANY FULL OUTER JOIN \n(\n SELECT 1 AS a\n) USING (a)\nWHERE b = 0 -------Need push down------- -SELECT toString(value) AS value\nFROM \n(\n SELECT 1 AS value\n WHERE toString(value) = \'1\'\n) \nWHERE value = \'1\' +SELECT toString(value) AS value\nFROM \n(\n SELECT 1 AS value\n WHERE toString(value) = \'1\'\n)\nWHERE value = \'1\' 1 -SELECT id\nFROM \n(\n SELECT 1 AS id\n WHERE id = 1\n UNION ALL\n SELECT 2 AS `2`\n WHERE `2` = 1\n) \nWHERE id = 1 +SELECT id\nFROM \n(\n SELECT 1 AS id\n WHERE id = 1\n UNION ALL\n SELECT 2 AS `2`\n WHERE `2` = 1\n)\nWHERE id = 1 1 -SELECT id\nFROM \n(\n SELECT arrayJoin([1, 2, 3]) AS id\n WHERE id = 1\n) \nWHERE id = 1 +SELECT id\nFROM \n(\n SELECT arrayJoin([1, 2, 3]) AS id\n WHERE id = 1\n)\nWHERE id = 1 1 -SELECT id\nFROM \n(\n SELECT arrayJoin([1, 2, 3]) AS id\n WHERE id = 1\n) \nWHERE id = 1 +SELECT id\nFROM \n(\n SELECT arrayJoin([1, 2, 3]) AS id\n WHERE id = 1\n)\nWHERE id = 1 1 -SELECT \n id, \n subquery\nFROM \n(\n SELECT \n 1 AS id, \n CAST(1, \'UInt8\') AS subquery\n WHERE subquery = 1\n) \nWHERE subquery = 1 +SELECT \n id, \n subquery\nFROM \n(\n SELECT \n 1 AS id, \n CAST(1, \'UInt8\') AS subquery\n WHERE subquery = 1\n)\nWHERE subquery = 1 1 1 -SELECT \n a, \n b\nFROM \n(\n SELECT \n toUInt64(sum(id) AS b) AS a, \n b\n FROM test_00597 \n HAVING a = 3\n) \nWHERE a = 3 +SELECT \n a, \n b\nFROM \n(\n SELECT \n toUInt64(sum(id) AS b) AS a, \n b\n FROM test_00597\n HAVING a = 3\n)\nWHERE a = 3 3 3 -SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n name, \n value, \n min(id) AS id\n FROM test_00597 \n GROUP BY \n date, \n name, \n value\n HAVING id = 1\n) \nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n name, \n value, \n min(id) AS id\n FROM test_00597\n GROUP BY \n date, \n name, \n value\n HAVING id = 1\n)\nWHERE id = 1 2000-01-01 1 test string 1 1 -SELECT \n a, \n b\nFROM \n(\n SELECT \n toUInt64(sum(id) AS b) AS a, \n b\n FROM test_00597 AS table_alias \n HAVING b = 3\n) AS outer_table_alias \nWHERE b = 3 +SELECT \n a, \n b\nFROM \n(\n SELECT \n toUInt64(sum(id) AS b) AS a, \n b\n FROM test_00597 AS table_alias\n HAVING b = 3\n) AS outer_table_alias\nWHERE b = 3 3 3 -SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n) \nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n)\nWHERE id = 1 2000-01-01 1 test string 1 1 -SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n ) \n WHERE id = 1\n) \nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n )\n WHERE id = 1\n)\nWHERE id = 1 2000-01-01 1 test string 1 1 -SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n ) AS b \n WHERE id = 1\n) \nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n ) AS b\n WHERE id = 1\n)\nWHERE id = 1 2000-01-01 1 test string 1 1 -SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n) \nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n)\nWHERE id = 1 2000-01-01 1 test string 1 1 -SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n ) \n WHERE id = 1\n) \nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n )\n WHERE id = 1\n)\nWHERE id = 1 2000-01-01 1 test string 1 1 -SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n) AS b \nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n) AS b\nWHERE id = 1 2000-01-01 1 test string 1 1 -SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n ) AS a \n WHERE id = 1\n) AS b \nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n ) AS a\n WHERE id = 1\n) AS b\nWHERE id = 1 2000-01-01 1 test string 1 1 -SELECT \n id, \n date, \n value\nFROM \n(\n SELECT \n id, \n date, \n min(value) AS value\n FROM test_00597 \n WHERE id = 1\n GROUP BY \n id, \n date\n) \nWHERE id = 1 +SELECT \n id, \n date, \n value\nFROM \n(\n SELECT \n id, \n date, \n min(value) AS value\n FROM test_00597\n WHERE id = 1\n GROUP BY \n id, \n date\n)\nWHERE id = 1 1 2000-01-01 1 -SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n UNION ALL\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n) \nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n UNION ALL\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n)\nWHERE id = 1 2000-01-01 1 test string 1 1 2000-01-01 1 test string 1 1 -SELECT \n date, \n id, \n name, \n value, \n date, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n) \nANY LEFT JOIN \n(\n SELECT *\n FROM test_00597 \n) USING (id)\nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value, \n date, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n)\nANY LEFT JOIN \n(\n SELECT *\n FROM test_00597\n) USING (id)\nWHERE id = 1 2000-01-01 1 test string 1 1 2000-01-01 test string 1 1 -SELECT \n id, \n date, \n name, \n value\nFROM \n(\n SELECT toInt8(1) AS id\n) \nANY LEFT JOIN \n(\n SELECT *\n FROM test_00597 \n) AS test_00597 USING (id)\nWHERE value = 1 +SELECT \n id, \n date, \n name, \n value\nFROM \n(\n SELECT toInt8(1) AS id\n)\nANY LEFT JOIN \n(\n SELECT *\n FROM test_00597\n) AS test_00597 USING (id)\nWHERE value = 1 1 2000-01-01 test string 1 1 -SELECT value\nFROM \n(\n SELECT toInt8(1) AS id\n) \nANY LEFT JOIN test_00597 AS b USING (id)\nWHERE value = 1 +SELECT value\nFROM \n(\n SELECT toInt8(1) AS id\n)\nANY LEFT JOIN test_00597 AS b USING (id)\nWHERE value = 1 1 -SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value, \n date, \n name, \n value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n ) \n ANY LEFT JOIN \n (\n SELECT *\n FROM test_00597 \n ) USING (id)\n WHERE id = 1\n) \nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value, \n date, \n name, \n value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n )\n ANY LEFT JOIN \n (\n SELECT *\n FROM test_00597\n ) USING (id)\n WHERE id = 1\n)\nWHERE id = 1 2000-01-01 1 test string 1 1 -SELECT \n date, \n id, \n name, \n value, \n b.date, \n b.name, \n b.value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n) \nANY LEFT JOIN \n(\n SELECT *\n FROM test_00597 \n) AS b USING (id)\nWHERE b.id = 1 +SELECT \n date, \n id, \n name, \n value, \n b.date, \n b.name, \n b.value\nFROM \n(\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n)\nANY LEFT JOIN \n(\n SELECT *\n FROM test_00597\n) AS b USING (id)\nWHERE b.id = 1 2000-01-01 1 test string 1 1 2000-01-01 test string 1 1 -SELECT \n id, \n date, \n name, \n value\nFROM \n(\n SELECT \n toInt8(1) AS id, \n toDate(\'2000-01-01\') AS date\n FROM system.numbers \n LIMIT 1\n) \nANY LEFT JOIN \n(\n SELECT *\n FROM test_00597 \n) AS b USING (date, id)\nWHERE b.date = toDate(\'2000-01-01\') +SELECT \n id, \n date, \n name, \n value\nFROM \n(\n SELECT \n toInt8(1) AS id, \n toDate(\'2000-01-01\') AS date\n FROM system.numbers\n LIMIT 1\n)\nANY LEFT JOIN \n(\n SELECT *\n FROM test_00597\n) AS b USING (date, id)\nWHERE b.date = toDate(\'2000-01-01\') 1 2000-01-01 test string 1 1 -SELECT \n date, \n id, \n name, \n value, \n `b.date`, \n `b.id`, \n `b.name`, \n `b.value`\nFROM \n(\n SELECT \n date, \n id, \n name, \n value, \n b.date, \n b.id, \n b.name, \n b.value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597 \n WHERE id = 1\n ) AS a \n ANY LEFT JOIN \n (\n SELECT *\n FROM test_00597 \n ) AS b ON id = b.id\n WHERE id = 1\n) \nWHERE id = 1 +SELECT \n date, \n id, \n name, \n value, \n `b.date`, \n `b.id`, \n `b.name`, \n `b.value`\nFROM \n(\n SELECT \n date, \n id, \n name, \n value, \n b.date, \n b.id, \n b.name, \n b.value\n FROM \n (\n SELECT \n date, \n id, \n name, \n value\n FROM test_00597\n WHERE id = 1\n ) AS a\n ANY LEFT JOIN \n (\n SELECT *\n FROM test_00597\n ) AS b ON id = b.id\n WHERE id = 1\n)\nWHERE id = 1 2000-01-01 1 test string 1 1 2000-01-01 1 test string 1 1 diff --git a/dbms/tests/queries/0_stateless/00599_create_view_with_subquery.reference b/dbms/tests/queries/0_stateless/00599_create_view_with_subquery.reference index 311c1ed53a4..13e0f35b075 100644 --- a/dbms/tests/queries/0_stateless/00599_create_view_with_subquery.reference +++ b/dbms/tests/queries/0_stateless/00599_create_view_with_subquery.reference @@ -1 +1 @@ -CREATE VIEW default.test_view_00599 (`id` UInt64) AS SELECT * FROM default.test_00599 WHERE id = (SELECT 1) +CREATE VIEW default.test_view_00599 (`id` UInt64) AS SELECT * FROM default.test_00599 WHERE id = (SELECT 1) diff --git a/dbms/tests/queries/0_stateless/00600_replace_running_query.reference b/dbms/tests/queries/0_stateless/00600_replace_running_query.reference index 573541ac970..237dd6b5309 100644 --- a/dbms/tests/queries/0_stateless/00600_replace_running_query.reference +++ b/dbms/tests/queries/0_stateless/00600_replace_running_query.reference @@ -1 +1,5 @@ 0 +1 0 +3 0 +2 0 +44 diff --git a/dbms/tests/queries/0_stateless/00600_replace_running_query.sh b/dbms/tests/queries/0_stateless/00600_replace_running_query.sh index 6778bbce149..ce0a4e185ad 100755 --- a/dbms/tests/queries/0_stateless/00600_replace_running_query.sh +++ b/dbms/tests/queries/0_stateless/00600_replace_running_query.sh @@ -9,3 +9,16 @@ $CLICKHOUSE_CURL -sS "$CLICKHOUSE_URL?query_id=hello&replace_running_query=1" -d sleep 0.1 # First query (usually) should be received by the server after this sleep. $CLICKHOUSE_CURL -sS "$CLICKHOUSE_URL?query_id=hello&replace_running_query=1" -d 'SELECT 0' wait + +${CLICKHOUSE_CLIENT} --user=readonly --query_id=42 --query='SELECT 1, sleep(1)' & +sleep 0.1 +( ${CLICKHOUSE_CLIENT} --query_id=42 --query='SELECT 43' ||: ) 2>&1 | grep -F 'is already running by user' > /dev/null +wait + +${CLICKHOUSE_CLIENT} --query='SELECT 3, sleep(1)' & +sleep 0.1 +${CLICKHOUSE_CLIENT} --query_id=42 --query='SELECT 2, sleep(1)' & +sleep 0.1 +( ${CLICKHOUSE_CLIENT} --query_id=42 --replace_running_query=1 --queue_max_wait_ms=500 --query='SELECT 43' ||: ) 2>&1 | grep -F "can't be stopped" > /dev/null +${CLICKHOUSE_CLIENT} --query_id=42 --replace_running_query=1 --query='SELECT 44' +wait diff --git a/dbms/tests/queries/0_stateless/00634_performance_introspection_and_logging.sh b/dbms/tests/queries/0_stateless/00634_performance_introspection_and_logging.sh index 47acdd34a19..eb418277c8f 100755 --- a/dbms/tests/queries/0_stateless/00634_performance_introspection_and_logging.sh +++ b/dbms/tests/queries/0_stateless/00634_performance_introspection_and_logging.sh @@ -13,7 +13,7 @@ server_logs_file=${CLICKHOUSE_TMP}/$cur_name"_server.logs" server_logs="--server_logs_file=$server_logs_file" rm -f "$server_logs_file" -settings="$server_logs --log_queries=1 --log_query_threads=1 --log_profile_events=1 --log_query_settings=1" +settings="$server_logs --log_queries=1 --log_query_threads=1 --log_profile_events=1 --log_query_settings=1 --experimental_use_processors=0" # Test insert logging on each block and checkPacket() method diff --git a/dbms/tests/queries/0_stateless/00640_endsWith.sql b/dbms/tests/queries/0_stateless/00640_endsWith.sql index cd2e6a08e5c..c497f529954 100644 --- a/dbms/tests/queries/0_stateless/00640_endsWith.sql +++ b/dbms/tests/queries/0_stateless/00640_endsWith.sql @@ -12,4 +12,6 @@ INSERT INTO endsWith_test values ('11', '22', '33'), ('a', 'a', 'bb'), ('abc', ' SELECT COUNT() FROM endsWith_test WHERE endsWith(S1, S1); SELECT COUNT() FROM endsWith_test WHERE endsWith(S1, S2); SELECT COUNT() FROM endsWith_test WHERE endsWith(S2, S3); + +SELECT endsWith([], 'str'); -- { serverError 43 } DROP TABLE endsWith_test; diff --git a/dbms/tests/queries/0_stateless/00653_verification_monotonic_data_load.sh b/dbms/tests/queries/0_stateless/00653_verification_monotonic_data_load.sh index 4de52dc36b3..69c0db567df 100755 --- a/dbms/tests/queries/0_stateless/00653_verification_monotonic_data_load.sh +++ b/dbms/tests/queries/0_stateless/00653_verification_monotonic_data_load.sh @@ -22,12 +22,12 @@ ${CLICKHOUSE_CLIENT} --query="DROP TABLE IF EXISTS unsigned_integer_test_table;" ${CLICKHOUSE_CLIENT} --query="DROP TABLE IF EXISTS enum_test_table;" ${CLICKHOUSE_CLIENT} --query="DROP TABLE IF EXISTS date_test_table;" -${CLICKHOUSE_CLIENT} --query="CREATE TABLE string_test_table (val String) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1;" -${CLICKHOUSE_CLIENT} --query="CREATE TABLE fixed_string_test_table (val FixedString(1)) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1;" -${CLICKHOUSE_CLIENT} --query="CREATE TABLE signed_integer_test_table (val Int32) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1;" -${CLICKHOUSE_CLIENT} --query="CREATE TABLE unsigned_integer_test_table (val UInt32) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1;" -${CLICKHOUSE_CLIENT} --query="CREATE TABLE enum_test_table (val Enum16('hello' = 1, 'world' = 2, 'yandex' = 256, 'clickhouse' = 257)) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1;" -${CLICKHOUSE_CLIENT} --query="CREATE TABLE date_test_table (val Date) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1;" +${CLICKHOUSE_CLIENT} --query="CREATE TABLE string_test_table (val String) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1, index_granularity_bytes = 0;" +${CLICKHOUSE_CLIENT} --query="CREATE TABLE fixed_string_test_table (val FixedString(1)) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1, index_granularity_bytes = 0;" +${CLICKHOUSE_CLIENT} --query="CREATE TABLE signed_integer_test_table (val Int32) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1, index_granularity_bytes = 0;" +${CLICKHOUSE_CLIENT} --query="CREATE TABLE unsigned_integer_test_table (val UInt32) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1, index_granularity_bytes = 0;" +${CLICKHOUSE_CLIENT} --query="CREATE TABLE enum_test_table (val Enum16('hello' = 1, 'world' = 2, 'yandex' = 256, 'clickhouse' = 257)) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1, index_granularity_bytes = 0;" +${CLICKHOUSE_CLIENT} --query="CREATE TABLE date_test_table (val Date) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1, index_granularity_bytes = 0;" ${CLICKHOUSE_CLIENT} --query="INSERT INTO string_test_table VALUES ('0'), ('2'), ('2');" diff --git a/dbms/tests/queries/0_stateless/00702_join_on_dups.reference b/dbms/tests/queries/0_stateless/00702_join_on_dups.reference index 769d2941564..d874ac1f0cf 100644 --- a/dbms/tests/queries/0_stateless/00702_join_on_dups.reference +++ b/dbms/tests/queries/0_stateless/00702_join_on_dups.reference @@ -206,11 +206,21 @@ self right 8 l8 \N 8 l8 \N 9 l9 \N 9 l9 \N self right nullable +0 \N 4 l5 \N +0 \N 4 l6 \N +0 \N 5 l7 \N +0 \N 8 l8 \N +0 \N 9 l9 \N 1 l1 1 1 l1 1 2 l2 2 2 l2 2 2 l3 3 2 l3 3 3 l4 4 3 l4 4 self right nullable vs not nullable +0 \N 4 l5 \N +0 \N 4 l6 \N +0 \N 5 l7 \N +0 \N 8 l8 \N +0 \N 9 l9 \N 1 l1 1 1 l1 1 2 l2 2 2 l2 2 2 l3 3 2 l2 2 @@ -232,6 +242,11 @@ self full 8 l8 \N 8 l8 \N 9 l9 \N 9 l9 \N self full nullable +0 \N 4 l5 \N +0 \N 4 l6 \N +0 \N 5 l7 \N +0 \N 8 l8 \N +0 \N 9 l9 \N 1 l1 1 1 l1 1 2 l2 2 2 l2 2 2 l3 3 2 l3 3 @@ -242,6 +257,11 @@ self full nullable 8 l8 \N 0 \N 9 l9 \N 0 \N self full nullable vs not nullable +0 \N 4 l5 \N +0 \N 4 l6 \N +0 \N 5 l7 \N +0 \N 8 l8 \N +0 \N 9 l9 \N 1 l1 1 1 l1 1 2 l2 2 2 l2 2 2 l3 3 2 l2 2 diff --git a/dbms/tests/queries/0_stateless/00731_long_merge_tree_select_opened_files.sh b/dbms/tests/queries/0_stateless/00731_long_merge_tree_select_opened_files.sh index bb67ae9fa83..350c9b05ea8 100755 --- a/dbms/tests/queries/0_stateless/00731_long_merge_tree_select_opened_files.sh +++ b/dbms/tests/queries/0_stateless/00731_long_merge_tree_select_opened_files.sh @@ -18,7 +18,7 @@ $CLICKHOUSE_CLIENT $settings -q "INSERT INTO merge_tree_table SELECT (intHash64( $CLICKHOUSE_CLIENT $settings -q "OPTIMIZE TABLE merge_tree_table FINAL;" -toching_many_parts_query="SELECT count() from (SELECT toDayOfWeek(date) as m, id, count() FROM merge_tree_table GROUP BY id, m ORDER BY count() DESC LIMIT 10 SETTINGS max_threads = 1)" +toching_many_parts_query="SELECT count() FROM (SELECT toDayOfWeek(date) AS m, id, count() FROM merge_tree_table GROUP BY id, m ORDER BY count() DESC LIMIT 10 SETTINGS max_threads = 1)" $CLICKHOUSE_CLIENT $settings -q "$toching_many_parts_query" &> /dev/null $CLICKHOUSE_CLIENT $settings -q "SYSTEM FLUSH LOGS" diff --git a/dbms/tests/queries/0_stateless/00734_timeslot.sql b/dbms/tests/queries/0_stateless/00734_timeslot.sql index 51e6a3f5330..f9422ee8f16 100644 --- a/dbms/tests/queries/0_stateless/00734_timeslot.sql +++ b/dbms/tests/queries/0_stateless/00734_timeslot.sql @@ -2,3 +2,6 @@ SELECT timeSlot(toDateTime('2000-01-02 03:04:05', 'UTC')); SELECT timeSlots(toDateTime('2000-01-02 03:04:05', 'UTC'), toUInt32(10000)); SELECT timeSlots(toDateTime('2000-01-02 03:04:05', 'UTC'), toUInt32(10000), 600); SELECT timeSlots(toDateTime('2000-01-02 03:04:05', 'UTC'), toUInt32(600), 30); +SELECT timeSlots(toDateTime('2000-01-02 03:04:05', 'UTC'), 'wrong argument'); -- { serverError 43 } +SELECT timeSlots(toDateTime('2000-01-02 03:04:05', 'UTC'), toUInt32(600), 'wrong argument'); -- { serverError 43 } +SELECT timeSlots(toDateTime('2000-01-02 03:04:05', 'UTC'), toUInt32(600), 0); -- { serverError 44 } \ No newline at end of file diff --git a/dbms/tests/queries/0_stateless/00746_sql_fuzzy.pl b/dbms/tests/queries/0_stateless/00746_sql_fuzzy.pl index e0e510e72fc..dd12d9ffdfa 100755 --- a/dbms/tests/queries/0_stateless/00746_sql_fuzzy.pl +++ b/dbms/tests/queries/0_stateless/00746_sql_fuzzy.pl @@ -133,7 +133,7 @@ sub main { split /[\s;,]+/, $ENV{SQL_FUZZY_FUNCTIONS} || file_read($ENV{SQL_FUZZY_FILE_FUNCTIONS} || 'clickhouse-functions') - || '__inner_restore_projection__ __inner_build_projection_composition__ convertCharset one_or_zero findClusterValue findClusterIndex toNullable coalesce isNotNull pointInEllipses transform pow acos asin tan cos tgamma lgamma erfc erf sqrt log10 exp10 e visitParamExtractFloat visitParamExtractUInt decodeURLComponent cutURLParameter cutQueryStringAndFragment cutFragment cutWWW URLPathHierarchy URLHierarchy extractURLParameterNames extractURLParameter queryStringAndFragment pathFull sin topLevelDomain domainWithoutWWW domain protocol greatCircleDistance extract match positionCaseInsensitiveUTF8 positionCaseInsensitive positionUTF8 position replaceRegexpAll replaceRegexpOne arrayStringConcat splitByString splitByChar alphaTokens endsWith startsWith appendTrailingCharIfAbsent substringUTF8 concatAssumeInjective reverseUTF8 upperUTF8 __inner_project__ upper lower CRC32 length notEmpty trunc round roundAge roundDuration roundToExp2 reinterpretAsString reinterpretAsDateTime reinterpretAsDate reinterpretAsFloat64 reinterpretAsFloat32 reinterpretAsInt64 reinterpretAsInt8 reinterpretAsUInt32 toStartOfFiveMinute toISOYear toISOWeek concat toDecimal64 ifNull toStartOfDay toSecond addSeconds sleepEachRow materialize visitParamExtractInt toStartOfMinute toDayOfWeek toDayOfMonth bitShiftLeft emptyArrayUInt8 parseDateTimeBestEffort toTime toDateTimeOrNull toFloat32OrNull toInt16 IPv6NumToString atan substring arrayIntersect isInfinite toRelativeHourNum hex arrayEnumerateDense toUInt8OrZero toRelativeSecondNum toUInt64OrNull MACNumToString toInt32OrNull toDayOfYear toUnixTimestamp toString toDateOrZero subtractDays toMinute murmurHash3_64 murmurHash2_32 toUInt64 toUInt8 dictGetDateTime empty isFinite caseWithoutExpression caseWithoutExpr visitParamExtractRaw queryString dictGetInt32OrDefault caseWithExpression toInt8OrZero multiIf if intExp10 bitShiftRight less toUInt8OrNull toInt8OrNull bitmaskToArray toIntervalYear toFloat64OrZero dateDiff generateUUIDv4 arrayPopBack toIntervalMonth toUUID notEquals toInt16OrNull murmurHash2_64 hasAny toIntervalMinute isNull tupleElement replaceAll parseDateTimeBestEffortOrZero toFloat32OrZero lowerUTF8 notIn gcd like regionToPopulation MACStringToOUI notLike toStringCutToZero lcm parseDateTimeBestEffortOrNull not toInt32OrZero arrayFilter toInt16OrZero range equals now toTypeName toUInt32OrNull emptyArrayString dictGetDateTimeOrDefault bitRotateRight cutIPv6 toUInt32OrZero timezone reverse runningDifferenceStartingWithFirstValue toDateTime arrayPopFront toInt32 intHash64 extractURLParameters lowCardinalityIndices toStartOfMonth toYear hasAll rowNumberInAllBlocks bitTestAll arrayCount arraySort abs bitNot intDiv intDivOrZero firstSignificantSubdomain dictGetFloat32OrDefault reinterpretAsUInt16 toHour minus regionToArea unhex IPv4StringToNum toIntervalHour toInt8 dictGetFloat32 log IPv4NumToString modulo arrayEnumerate cutQueryString reinterpretAsFixedString countEqual bitTest toDecimal128 plus or reinterpretAsUInt64 toMonth visitParamExtractBool emptyArrayUInt64 replaceOne arrayReverseSort toFloat32 toRelativeMonthNum emptyArrayInt32 toRelativeYearNum arrayElement log2 array arrayReverse toUInt64OrZero emptyArrayFloat64 negate arrayPushBack subtractWeeks bitTestAny bitAnd toDecimal32 arrayPushFront lessOrEquals intExp2 toUInt16OrZero arrayConcat arrayCumSum arraySlice addDays dictGetUInt8 toUInt32 bitOr caseWithExpr toStartOfYear toIntervalDay MD5 emptyArrayUInt32 emptyArrayInt8 toMonday addMonths arrayUniq SHA256 arrayExists multiply toUInt16OrNull dictGetInt8 visitParamHas emptyArrayInt64 toIntervalSecond toDate sleep emptyArrayToSingle path toInt64OrZero SHA1 extractAll emptyArrayDate dumpColumnStructure toInt64 lengthUTF8 greatest arrayEnumerateUniq arrayDistinct arrayFirst toFixedString IPv4NumToStringClassC toFloat64OrNull IPv4ToIPv6 identity ceil toStartOfQuarter dictGetInt8OrDefault MACStringToNum emptyArrayUInt16 UUIDStringToNum dictGetUInt16 toStartOfFifteenMinutes toStartOfHour sumburConsistentHash toStartOfISOYear toRelativeQuarterNum toRelativeWeekNum toRelativeDayNum cbrt yesterday bitXor timeSlot timeSlots emptyArrayInt16 dictGetInt16 toYYYYMM toYYYYMMDDhhmmss toUInt16 addMinutes addHours addWeeks nullIf subtractSeconds subtractMinutes toIntervalWeek subtractHours isNaN subtractMonths toDateOrNull subtractYears toTimeZone formatDateTime has cityHash64 intHash32 fragment regionToCity indexOf regionToDistrict regionToCountry visibleWidth regionToContinent regionToTopContinent toColumnTypeName regionHierarchy CHAR_LENGTH least divide SEHierarchy dictGetDate OSToRoot SEToRoot OSIn SEIn regionToName dictGetStringOrDefault OSHierarchy exp floor dictGetUInt8OrDefault dictHas dictGetUInt64 cutToFirstSignificantSubdomain dictGetInt32 pointInPolygon dictGetInt64 blockNumber IPv6StringToNum dictGetString dictGetFloat64 dictGetUUID CHARACTER_LENGTH toQuarter dictGetHierarchy toFloat64 arraySum toInt64OrNull dictIsIn dictGetUInt16OrDefault dictGetUInt32OrDefault emptyArrayDateTime greater jumpConsistentHash dictGetUInt64OrDefault dictGetInt16OrDefault dictGetInt64OrDefault reinterpretAsInt32 dictGetUInt32 murmurHash3_32 bar dictGetUUIDOrDefault rand modelEvaluate arrayReduce farmHash64 bitmaskToList formatReadableSize halfMD5 SHA224 arrayMap sipHash64 dictGetFloat64OrDefault sipHash128 metroHash64 murmurHash3_128 yandexConsistentHash emptyArrayFloat32 arrayAll toYYYYMMDD today arrayFirstIndex greaterOrEquals arrayDifference visitParamExtractString toDateTimeOrZero globalNotIn throwIf and xor currentDatabase hostName URLHash getSizeOfEnumType defaultValueOfArgumentType blockSize tuple arrayCumSumNonNegative rowNumberInBlock arrayResize ignore toRelativeMinuteNum indexHint reinterpretAsInt16 addYears arrayJoin replicate hasColumnInTable version regionIn uptime runningAccumulate runningDifference assumeNotNull pi finalizeAggregation toLowCardinality exp2 lowCardinalityKeys in globalIn dictGetDateOrDefault rand64 CAST bitRotateLeft randConstant UUIDNumToString reinterpretAsUInt8 truncate ceiling retention maxIntersections groupBitXor groupBitOr uniqUpTo uniqCombined uniqExact uniq covarPop stddevPop varPop covarSamp varSamp sumMap corrStable corr quantileTiming quantileDeterministic quantilesExact uniqHLL12 quantilesTiming covarPopStable stddevSampStable quantilesExactWeighted quantileExactWeighted quantileTimingWeighted quantileExact quantilesDeterministic quantiles topK sumWithOverflow count groupArray stddevSamp groupArrayInsertAt quantile quantilesTimingWeighted quantileTDigest quantilesTDigest windowFunnel min argMax varSampStable maxIntersectionsPosition quantilesTDigestWeighted groupUniqArray sequenceCount sumKahan any anyHeavy histogram quantileTDigestWeighted max groupBitAnd argMin varPopStable avg sequenceMatch stddevPopStable sum anyLast covarSampStable BIT_XOR medianExactWeighted medianTiming medianExact median medianDeterministic VAR_SAMP STDDEV_POP medianTDigest VAR_POP medianTDigestWeighted BIT_OR STDDEV_SAMP medianTimingWeighted COVAR_SAMP COVAR_POP BIT_AND' + || '__inner_restore_projection__ __inner_build_projection_composition__ convertCharset one_or_zero findClusterValue findClusterIndex toNullable coalesce isNotNull geoToH3 pointInEllipses transform pow acos asin tan cos tgamma lgamma erfc erf sqrt log10 exp10 e visitParamExtractFloat visitParamExtractUInt decodeURLComponent cutURLParameter cutQueryStringAndFragment cutFragment cutWWW URLPathHierarchy URLHierarchy extractURLParameterNames extractURLParameter queryStringAndFragment pathFull sin topLevelDomain domainWithoutWWW domain protocol greatCircleDistance extract match positionCaseInsensitiveUTF8 positionCaseInsensitive positionUTF8 position replaceRegexpAll replaceRegexpOne arrayStringConcat splitByString splitByChar alphaTokens endsWith startsWith appendTrailingCharIfAbsent substringUTF8 concatAssumeInjective reverseUTF8 upperUTF8 __inner_project__ upper lower CRC32 length notEmpty trunc round roundAge roundDuration roundToExp2 reinterpretAsString reinterpretAsDateTime reinterpretAsDate reinterpretAsFloat64 reinterpretAsFloat32 reinterpretAsInt64 reinterpretAsInt8 reinterpretAsUInt32 toStartOfFiveMinute toISOYear toISOWeek concat toDecimal64 ifNull toStartOfDay toSecond addSeconds sleepEachRow materialize visitParamExtractInt toStartOfMinute toDayOfWeek toDayOfMonth bitShiftLeft emptyArrayUInt8 parseDateTimeBestEffort toTime toDateTimeOrNull toFloat32OrNull toInt16 IPv6NumToString atan substring arrayIntersect isInfinite toRelativeHourNum hex arrayEnumerateDense toUInt8OrZero toRelativeSecondNum toUInt64OrNull MACNumToString toInt32OrNull toDayOfYear toUnixTimestamp toString toDateOrZero subtractDays toMinute murmurHash3_64 murmurHash2_32 toUInt64 toUInt8 dictGetDateTime empty isFinite caseWithoutExpression caseWithoutExpr visitParamExtractRaw queryString dictGetInt32OrDefault caseWithExpression toInt8OrZero multiIf if intExp10 bitShiftRight less toUInt8OrNull toInt8OrNull bitmaskToArray toIntervalYear toFloat64OrZero dateDiff generateUUIDv4 arrayPopBack toIntervalMonth toUUID notEquals toInt16OrNull murmurHash2_64 hasAny toIntervalMinute isNull tupleElement replaceAll parseDateTimeBestEffortOrZero toFloat32OrZero lowerUTF8 notIn gcd like regionToPopulation MACStringToOUI notLike toStringCutToZero lcm parseDateTimeBestEffortOrNull not toInt32OrZero arrayFilter toInt16OrZero range equals now toTypeName toUInt32OrNull emptyArrayString dictGetDateTimeOrDefault bitRotateRight cutIPv6 toUInt32OrZero timezone reverse runningDifferenceStartingWithFirstValue toDateTime arrayPopFront toInt32 intHash64 extractURLParameters lowCardinalityIndices toStartOfMonth toYear hasAll rowNumberInAllBlocks bitTestAll arrayCount arraySort abs bitNot intDiv intDivOrZero firstSignificantSubdomain dictGetFloat32OrDefault reinterpretAsUInt16 toHour minus regionToArea unhex IPv4StringToNum toIntervalHour toInt8 dictGetFloat32 log IPv4NumToString modulo arrayEnumerate cutQueryString reinterpretAsFixedString countEqual bitTest toDecimal128 plus or reinterpretAsUInt64 toMonth visitParamExtractBool emptyArrayUInt64 replaceOne arrayReverseSort toFloat32 toRelativeMonthNum emptyArrayInt32 toRelativeYearNum arrayElement log2 array arrayReverse toUInt64OrZero emptyArrayFloat64 negate arrayPushBack subtractWeeks bitTestAny bitAnd toDecimal32 arrayPushFront lessOrEquals intExp2 toUInt16OrZero arrayConcat arrayCumSum arraySlice addDays dictGetUInt8 toUInt32 bitOr caseWithExpr toStartOfYear toIntervalDay MD5 emptyArrayUInt32 emptyArrayInt8 toMonday addMonths arrayUniq SHA256 arrayExists multiply toUInt16OrNull dictGetInt8 visitParamHas emptyArrayInt64 toIntervalSecond toDate sleep emptyArrayToSingle path toInt64OrZero SHA1 extractAll emptyArrayDate dumpColumnStructure toInt64 lengthUTF8 greatest arrayEnumerateUniq arrayDistinct arrayFirst toFixedString IPv4NumToStringClassC toFloat64OrNull IPv4ToIPv6 identity ceil toStartOfQuarter dictGetInt8OrDefault MACStringToNum emptyArrayUInt16 UUIDStringToNum dictGetUInt16 toStartOfFifteenMinutes toStartOfHour sumburConsistentHash toStartOfISOYear toRelativeQuarterNum toRelativeWeekNum toRelativeDayNum cbrt yesterday bitXor timeSlot timeSlots emptyArrayInt16 dictGetInt16 toYYYYMM toYYYYMMDDhhmmss toUInt16 addMinutes addHours addWeeks nullIf subtractSeconds subtractMinutes toIntervalWeek subtractHours isNaN subtractMonths toDateOrNull subtractYears toTimeZone formatDateTime has cityHash64 intHash32 fragment regionToCity indexOf regionToDistrict regionToCountry visibleWidth regionToContinent regionToTopContinent toColumnTypeName regionHierarchy CHAR_LENGTH least divide SEHierarchy dictGetDate OSToRoot SEToRoot OSIn SEIn regionToName dictGetStringOrDefault OSHierarchy exp floor dictGetUInt8OrDefault dictHas dictGetUInt64 cutToFirstSignificantSubdomain dictGetInt32 pointInPolygon dictGetInt64 blockNumber IPv6StringToNum dictGetString dictGetFloat64 dictGetUUID CHARACTER_LENGTH toQuarter dictGetHierarchy toFloat64 arraySum toInt64OrNull dictIsIn dictGetUInt16OrDefault dictGetUInt32OrDefault emptyArrayDateTime greater jumpConsistentHash dictGetUInt64OrDefault dictGetInt16OrDefault dictGetInt64OrDefault reinterpretAsInt32 dictGetUInt32 murmurHash3_32 bar dictGetUUIDOrDefault rand modelEvaluate arrayReduce farmHash64 bitmaskToList formatReadableSize halfMD5 SHA224 arrayMap sipHash64 dictGetFloat64OrDefault sipHash128 metroHash64 murmurHash3_128 yandexConsistentHash emptyArrayFloat32 arrayAll toYYYYMMDD today arrayFirstIndex greaterOrEquals arrayDifference visitParamExtractString toDateTimeOrZero globalNotIn throwIf and xor currentDatabase hostName URLHash getSizeOfEnumType defaultValueOfArgumentType blockSize tuple arrayCumSumNonNegative rowNumberInBlock arrayResize ignore toRelativeMinuteNum indexHint reinterpretAsInt16 addYears arrayJoin replicate hasColumnInTable version regionIn uptime runningAccumulate runningDifference assumeNotNull pi finalizeAggregation toLowCardinality exp2 lowCardinalityKeys in globalIn dictGetDateOrDefault rand64 CAST bitRotateLeft randConstant UUIDNumToString reinterpretAsUInt8 truncate ceiling retention maxIntersections groupBitXor groupBitOr uniqUpTo uniqCombined uniqExact uniq covarPop stddevPop varPop covarSamp varSamp sumMap corrStable corr quantileTiming quantileDeterministic quantilesExact uniqHLL12 quantilesTiming covarPopStable stddevSampStable quantilesExactWeighted quantileExactWeighted quantileTimingWeighted quantileExact quantilesDeterministic quantiles topK sumWithOverflow count groupArray stddevSamp groupArrayInsertAt quantile quantilesTimingWeighted quantileTDigest quantilesTDigest windowFunnel min argMax varSampStable maxIntersectionsPosition quantilesTDigestWeighted groupUniqArray sequenceCount sumKahan any anyHeavy histogram quantileTDigestWeighted max groupBitAnd argMin varPopStable avg sequenceMatch stddevPopStable sum anyLast covarSampStable BIT_XOR medianExactWeighted medianTiming medianExact median medianDeterministic VAR_SAMP STDDEV_POP medianTDigest VAR_POP medianTDigestWeighted BIT_OR STDDEV_SAMP medianTimingWeighted COVAR_SAMP COVAR_POP BIT_AND' ]; # $functions = [grep { not $_ ~~ [qw( )] } @$functions]; # will be removed # select name from system.table_functions format TSV; diff --git a/dbms/tests/queries/0_stateless/00751_default_databasename_for_view.reference b/dbms/tests/queries/0_stateless/00751_default_databasename_for_view.reference index 35217410c2d..e45dde1921e 100644 --- a/dbms/tests/queries/0_stateless/00751_default_databasename_for_view.reference +++ b/dbms/tests/queries/0_stateless/00751_default_databasename_for_view.reference @@ -1,4 +1,4 @@ -CREATE MATERIALIZED VIEW test.t_mv_00751 (`date` Date, `platform` Enum8('a' = 0, 'b' = 1), `app` Enum8('a' = 0, 'b' = 1)) ENGINE = MergeTree ORDER BY date SETTINGS index_granularity = 8192 AS SELECT date, platform, app FROM test.t_00751 WHERE (app = (SELECT min(app) FROM test.u_00751 )) AND (platform = (SELECT (SELECT min(platform) FROM test.v_00751 ))) +CREATE MATERIALIZED VIEW test.t_mv_00751 (`date` Date, `platform` Enum8('a' = 0, 'b' = 1), `app` Enum8('a' = 0, 'b' = 1)) ENGINE = MergeTree ORDER BY date SETTINGS index_granularity = 8192 AS SELECT date, platform, app FROM test.t_00751 WHERE (app = (SELECT min(app) FROM test.u_00751)) AND (platform = (SELECT (SELECT min(platform) FROM test.v_00751))) 2000-01-01 a a 2000-01-02 b b 2000-01-03 a a diff --git a/dbms/tests/queries/0_stateless/00753_quantile_format.reference b/dbms/tests/queries/0_stateless/00753_quantile_format.reference index e61cee21c64..04bb0000b3e 100644 --- a/dbms/tests/queries/0_stateless/00753_quantile_format.reference +++ b/dbms/tests/queries/0_stateless/00753_quantile_format.reference @@ -6,6 +6,10 @@ ['2016-06-15 23:00:00'] 2016-06-15 23:00:00 ['2016-06-15 23:00:00'] +30000 +[30000] +30000 +[30000] 2016-06-15 23:01:04 ['2016-06-15 23:01:04'] 2016-06-15 23:01:04 diff --git a/dbms/tests/queries/0_stateless/00753_quantile_format.sql b/dbms/tests/queries/0_stateless/00753_quantile_format.sql index 3a0947015ea..24cf0e4bf90 100644 --- a/dbms/tests/queries/0_stateless/00753_quantile_format.sql +++ b/dbms/tests/queries/0_stateless/00753_quantile_format.sql @@ -15,11 +15,11 @@ SELECT quantilesExact(0.2)(d) FROM datetime; SELECT quantileExactWeighted(0.2)(d, 1) FROM datetime; SELECT quantilesExactWeighted(0.2)(d, 1) FROM datetime; -SELECT quantileTiming(0.2)(d) FROM datetime; -- { serverError 43 } -SELECT quantilesTiming(0.2)(d) FROM datetime; -- { serverError 43 } +SELECT quantileTiming(0.2)(d) FROM datetime; +SELECT quantilesTiming(0.2)(d) FROM datetime; -SELECT quantileTimingWeighted(0.2)(d, 1) FROM datetime; -- { serverError 43 } -SELECT quantilesTimingWeighted(0.2)(d, 1) FROM datetime; -- { serverError 43 } +SELECT quantileTimingWeighted(0.2)(d, 1) FROM datetime; +SELECT quantilesTimingWeighted(0.2)(d, 1) FROM datetime; SELECT quantileTDigest(0.2)(d) FROM datetime; SELECT quantilesTDigest(0.2)(d) FROM datetime; diff --git a/dbms/tests/queries/0_stateless/00804_test_delta_codec_compression.reference b/dbms/tests/queries/0_stateless/00804_test_delta_codec_compression.reference index 3f28f9fad72..79302586e92 100644 --- a/dbms/tests/queries/0_stateless/00804_test_delta_codec_compression.reference +++ b/dbms/tests/queries/0_stateless/00804_test_delta_codec_compression.reference @@ -1,6 +1,6 @@ -91 +83 1 46 1 -33 +32 1 diff --git a/dbms/tests/queries/0_stateless/00826_cross_to_inner_join.reference b/dbms/tests/queries/0_stateless/00826_cross_to_inner_join.reference index 04c21a1e29a..24649ea3acb 100644 --- a/dbms/tests/queries/0_stateless/00826_cross_to_inner_join.reference +++ b/dbms/tests/queries/0_stateless/00826_cross_to_inner_join.reference @@ -56,26 +56,26 @@ comma nullable 1 1 1 1 2 2 1 2 cross -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nCROSS JOIN \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 \nWHERE a = t2_00826.a -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 ON a = t2_00826.a\nWHERE a = t2_00826.a +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nCROSS JOIN \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826\nWHERE a = t2_00826.a +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826 ON a = t2_00826.a\nWHERE a = t2_00826.a cross nullable -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \n, \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 \nWHERE a = t2_00826.a -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 ON a = t2_00826.a\nWHERE a = t2_00826.a +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\n, \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826\nWHERE a = t2_00826.a +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826 ON a = t2_00826.a\nWHERE a = t2_00826.a cross nullable vs not nullable -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nCROSS JOIN \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 \nWHERE a = t2_00826.b -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 ON a = t2_00826.b\nWHERE a = t2_00826.b +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nCROSS JOIN \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826\nWHERE a = t2_00826.b +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826 ON a = t2_00826.b\nWHERE a = t2_00826.b cross self -SELECT \n a, \n b, \n y.a, \n y.b\nFROM t1_00826 AS x \nCROSS JOIN t1_00826 AS y \nWHERE (a = y.a) AND (b = y.b) -SELECT \n a, \n b, \n y.a, \n y.b\nFROM t1_00826 AS x \nALL INNER JOIN t1_00826 AS y ON (a = y.a) AND (b = y.b)\nWHERE (a = y.a) AND (b = y.b) +SELECT \n a, \n b, \n y.a, \n y.b\nFROM t1_00826 AS x\nCROSS JOIN t1_00826 AS y\nWHERE (a = y.a) AND (b = y.b) +SELECT \n a, \n b, \n y.a, \n y.b\nFROM t1_00826 AS x\nALL INNER JOIN t1_00826 AS y ON (a = y.a) AND (b = y.b)\nWHERE (a = y.a) AND (b = y.b) cross one table expr -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nCROSS JOIN \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 \nWHERE a = b -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nCROSS JOIN \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 \nWHERE a = b +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nCROSS JOIN \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826\nWHERE a = b +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nCROSS JOIN \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826\nWHERE a = b cross multiple ands -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nCROSS JOIN \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 \nWHERE (a = t2_00826.a) AND (b = t2_00826.b) -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 ON (a = t2_00826.a) AND (b = t2_00826.b)\nWHERE (a = t2_00826.a) AND (b = t2_00826.b) +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nCROSS JOIN \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826\nWHERE (a = t2_00826.a) AND (b = t2_00826.b) +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826 ON (a = t2_00826.a) AND (b = t2_00826.b)\nWHERE (a = t2_00826.a) AND (b = t2_00826.b) cross and inside and -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nCROSS JOIN \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 \nWHERE (a = t2_00826.a) AND ((a = t2_00826.a) AND ((a = t2_00826.a) AND (b = t2_00826.b))) -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826 \n) AS t2_00826 ON (a = t2_00826.a) AND (a = t2_00826.a) AND (a = t2_00826.a) AND (b = t2_00826.b)\nWHERE (a = t2_00826.a) AND ((a = t2_00826.a) AND ((a = t2_00826.a) AND (b = t2_00826.b))) +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nCROSS JOIN \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826\nWHERE (a = t2_00826.a) AND ((a = t2_00826.a) AND ((a = t2_00826.a) AND (b = t2_00826.b))) +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826\n) AS t2_00826 ON (a = t2_00826.a) AND (a = t2_00826.a) AND (a = t2_00826.a) AND (b = t2_00826.b)\nWHERE (a = t2_00826.a) AND ((a = t2_00826.a) AND ((a = t2_00826.a) AND (b = t2_00826.b))) cross split conjunction -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nCROSS JOIN \n(\n SELECT *\n FROM t2_00826 \n WHERE b > 0\n) AS t2_00826 \nWHERE (a = t2_00826.a) AND (b = t2_00826.b) AND (a >= 1) AND (t2_00826.b > 0) -SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826 \nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826 \n WHERE b > 0\n) AS t2_00826 ON (a = t2_00826.a) AND (b = t2_00826.b)\nWHERE (a = t2_00826.a) AND (b = t2_00826.b) AND (a >= 1) AND (t2_00826.b > 0) +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nCROSS JOIN \n(\n SELECT *\n FROM t2_00826\n WHERE b > 0\n) AS t2_00826\nWHERE (a = t2_00826.a) AND (b = t2_00826.b) AND (a >= 1) AND (t2_00826.b > 0) +SELECT \n a, \n b, \n t2_00826.a, \n t2_00826.b\nFROM t1_00826\nALL INNER JOIN \n(\n SELECT *\n FROM t2_00826\n WHERE b > 0\n) AS t2_00826 ON (a = t2_00826.a) AND (b = t2_00826.b)\nWHERE (a = t2_00826.a) AND (b = t2_00826.b) AND (a >= 1) AND (t2_00826.b > 0) diff --git a/dbms/tests/queries/0_stateless/00840_top_k_weighted.reference b/dbms/tests/queries/0_stateless/00840_top_k_weighted.reference index 1562820da86..2f681940a86 100644 --- a/dbms/tests/queries/0_stateless/00840_top_k_weighted.reference +++ b/dbms/tests/queries/0_stateless/00840_top_k_weighted.reference @@ -1,2 +1,3 @@ ['hello','world'] ['hello','world'] ['goodbye','hello'] ['hello','world'] +[99,98,97,96,95] diff --git a/dbms/tests/queries/0_stateless/00840_top_k_weighted.sql b/dbms/tests/queries/0_stateless/00840_top_k_weighted.sql index 655e9d0ad72..e5ef3aa9d85 100644 --- a/dbms/tests/queries/0_stateless/00840_top_k_weighted.sql +++ b/dbms/tests/queries/0_stateless/00840_top_k_weighted.sql @@ -1,2 +1,3 @@ SELECT topKWeighted(2)(x, weight), topK(2)(x) FROM (SELECT t.1 AS x, t.2 AS weight FROM (SELECT arrayJoin([('hello', 1), ('world', 1), ('goodbye', 1), ('abc', 1)]) AS t)); SELECT topKWeighted(2)(x, weight), topK(2)(x) FROM (SELECT t.1 AS x, t.2 AS weight FROM (SELECT arrayJoin([('hello', 1), ('world', 1), ('goodbye', 2), ('abc', 1)]) AS t)); +SELECT topKWeighted(5)(n, weight) FROM (SELECT number as n, number as weight from system.numbers LIMIT 100); diff --git a/dbms/tests/queries/0_stateless/00849_multiple_comma_join.reference b/dbms/tests/queries/0_stateless/00849_multiple_comma_join.reference index 6a3ccd22249..e1256053739 100644 --- a/dbms/tests/queries/0_stateless/00849_multiple_comma_join.reference +++ b/dbms/tests/queries/0_stateless/00849_multiple_comma_join.reference @@ -1,17 +1,17 @@ -SELECT a\nFROM t1_00849 \nCROSS JOIN \n(\n SELECT *\n FROM t2_00849 \n) AS t2_00849 -SELECT a\nFROM t1_00849 \nALL INNER JOIN \n(\n SELECT *\n FROM t2_00849 \n) AS t2_00849 ON a = t2_00849.a\nWHERE a = t2_00849.a -SELECT a\nFROM t1_00849 \nALL INNER JOIN \n(\n SELECT *\n FROM t2_00849 \n) AS t2_00849 ON b = t2_00849.b\nWHERE b = t2_00849.b -SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849 \n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849 \n ) AS t2_00849 ON `--t1_00849.a` = `--t2_00849.a`\n WHERE `--t1_00849.a` = `--t2_00849.a`\n) \nALL INNER JOIN \n(\n SELECT *\n FROM t3_00849 \n) AS t3_00849 ON `--t1_00849.a` = a\nWHERE (`--t1_00849.a` = `--t2_00849.a`) AND (`--t1_00849.a` = a) -SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n a AS `--t1_00849.a`, \n b AS `--t1_00849.b`, \n t2_00849.a, \n t2_00849.b AS `--t2_00849.b`\n FROM t1_00849 \n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849 \n ) AS t2_00849 ON `--t1_00849.b` = `--t2_00849.b`\n WHERE `--t1_00849.b` = `--t2_00849.b`\n) \nALL INNER JOIN \n(\n SELECT *\n FROM t3_00849 \n) AS t3_00849 ON `--t1_00849.b` = b\nWHERE (`--t1_00849.b` = `--t2_00849.b`) AND (`--t1_00849.b` = b) -SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `--t2_00849.a`, \n `t2_00849.b`, \n a AS `--t3_00849.a`, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849 \n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849 \n ) AS t2_00849 ON `--t1_00849.a` = `--t2_00849.a`\n WHERE `--t1_00849.a` = `--t2_00849.a`\n ) \n ALL INNER JOIN \n (\n SELECT *\n FROM t3_00849 \n ) AS t3_00849 ON `--t1_00849.a` = `--t3_00849.a`\n WHERE (`--t1_00849.a` = `--t3_00849.a`) AND (`--t1_00849.a` = `--t2_00849.a`)\n) \nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849 \n) AS t4_00849 ON `--t1_00849.a` = a\nWHERE (`--t1_00849.a` = `--t2_00849.a`) AND (`--t1_00849.a` = `--t3_00849.a`) AND (`--t1_00849.a` = a) -SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n `--t1_00849.b`, \n `t2_00849.a`, \n `--t2_00849.b`, \n a, \n b AS `--t3_00849.b`\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b AS `--t1_00849.b`, \n t2_00849.a, \n t2_00849.b AS `--t2_00849.b`\n FROM t1_00849 \n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849 \n ) AS t2_00849 ON `--t1_00849.b` = `--t2_00849.b`\n WHERE `--t1_00849.b` = `--t2_00849.b`\n ) \n ALL INNER JOIN \n (\n SELECT *\n FROM t3_00849 \n ) AS t3_00849 ON `--t1_00849.b` = `--t3_00849.b`\n WHERE (`--t1_00849.b` = `--t3_00849.b`) AND (`--t1_00849.b` = `--t2_00849.b`)\n) \nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849 \n) AS t4_00849 ON `--t1_00849.b` = b\nWHERE (`--t1_00849.b` = `--t2_00849.b`) AND (`--t1_00849.b` = `--t3_00849.b`) AND (`--t1_00849.b` = b) -SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `--t2_00849.a`, \n `t2_00849.b`, \n a AS `--t3_00849.a`, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849 \n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849 \n ) AS t2_00849 ON `--t2_00849.a` = `--t1_00849.a`\n WHERE `--t2_00849.a` = `--t1_00849.a`\n ) \n ALL INNER JOIN \n (\n SELECT *\n FROM t3_00849 \n ) AS t3_00849 ON `--t2_00849.a` = `--t3_00849.a`\n WHERE (`--t2_00849.a` = `--t3_00849.a`) AND (`--t2_00849.a` = `--t1_00849.a`)\n) \nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849 \n) AS t4_00849 ON `--t2_00849.a` = a\nWHERE (`--t2_00849.a` = `--t1_00849.a`) AND (`--t2_00849.a` = `--t3_00849.a`) AND (`--t2_00849.a` = a) -SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `--t2_00849.a`, \n `t2_00849.b`, \n a AS `--t3_00849.a`, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849 \n CROSS JOIN \n (\n SELECT *\n FROM t2_00849 \n ) AS t2_00849 \n ) \n ALL INNER JOIN \n (\n SELECT *\n FROM t3_00849 \n ) AS t3_00849 ON (`--t3_00849.a` = `--t1_00849.a`) AND (`--t3_00849.a` = `--t2_00849.a`)\n WHERE (`--t3_00849.a` = `--t2_00849.a`) AND (`--t3_00849.a` = `--t1_00849.a`)\n) \nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849 \n) AS t4_00849 ON `--t3_00849.a` = a\nWHERE (`--t3_00849.a` = `--t1_00849.a`) AND (`--t3_00849.a` = `--t2_00849.a`) AND (`--t3_00849.a` = a) -SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `--t2_00849.a`, \n `t2_00849.b`, \n a AS `--t3_00849.a`, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849 \n CROSS JOIN \n (\n SELECT *\n FROM t2_00849 \n ) AS t2_00849 \n ) \n CROSS JOIN \n (\n SELECT *\n FROM t3_00849 \n ) AS t3_00849 \n) \nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849 \n) AS t4_00849 ON (a = `--t1_00849.a`) AND (a = `--t2_00849.a`) AND (a = `--t3_00849.a`)\nWHERE (a = `--t1_00849.a`) AND (a = `--t2_00849.a`) AND (a = `--t3_00849.a`) -SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `--t2_00849.a`, \n `t2_00849.b`, \n a AS `--t3_00849.a`, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849 \n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849 \n ) AS t2_00849 ON `--t1_00849.a` = `--t2_00849.a`\n WHERE `--t1_00849.a` = `--t2_00849.a`\n ) \n ALL INNER JOIN \n (\n SELECT *\n FROM t3_00849 \n ) AS t3_00849 ON `--t2_00849.a` = `--t3_00849.a`\n WHERE (`--t2_00849.a` = `--t3_00849.a`) AND (`--t1_00849.a` = `--t2_00849.a`)\n) \nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849 \n) AS t4_00849 ON `--t3_00849.a` = a\nWHERE (`--t1_00849.a` = `--t2_00849.a`) AND (`--t2_00849.a` = `--t3_00849.a`) AND (`--t3_00849.a` = a) -SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `t2_00849.a`, \n `t2_00849.b`, \n a, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a, \n t2_00849.b\n FROM t1_00849 \n CROSS JOIN \n (\n SELECT *\n FROM t2_00849 \n ) AS t2_00849 \n ) \n CROSS JOIN \n (\n SELECT *\n FROM t3_00849 \n ) AS t3_00849 \n) \nCROSS JOIN \n(\n SELECT *\n FROM t4_00849 \n) AS t4_00849 -SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `t2_00849.a`, \n `t2_00849.b`, \n a, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a, \n t2_00849.b\n FROM t1_00849 \n CROSS JOIN \n (\n SELECT *\n FROM t2_00849 \n ) AS t2_00849 \n ) \n CROSS JOIN \n (\n SELECT *\n FROM t3_00849 \n ) AS t3_00849 \n) \nCROSS JOIN \n(\n SELECT *\n FROM t4_00849 \n) AS t4_00849 -SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849 \n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849 \n ) AS t2_00849 ON `--t1_00849.a` = `--t2_00849.a`\n) \nCROSS JOIN \n(\n SELECT *\n FROM t3_00849 \n) AS t3_00849 +SELECT a\nFROM t1_00849\nCROSS JOIN \n(\n SELECT *\n FROM t2_00849\n) AS t2_00849 +SELECT a\nFROM t1_00849\nALL INNER JOIN \n(\n SELECT *\n FROM t2_00849\n) AS t2_00849 ON a = t2_00849.a\nWHERE a = t2_00849.a +SELECT a\nFROM t1_00849\nALL INNER JOIN \n(\n SELECT *\n FROM t2_00849\n) AS t2_00849 ON b = t2_00849.b\nWHERE b = t2_00849.b +SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849\n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849\n ) AS t2_00849 ON `--t1_00849.a` = `--t2_00849.a`\n WHERE `--t1_00849.a` = `--t2_00849.a`\n)\nALL INNER JOIN \n(\n SELECT *\n FROM t3_00849\n) AS t3_00849 ON `--t1_00849.a` = a\nWHERE (`--t1_00849.a` = `--t2_00849.a`) AND (`--t1_00849.a` = a) +SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n a AS `--t1_00849.a`, \n b AS `--t1_00849.b`, \n t2_00849.a, \n t2_00849.b AS `--t2_00849.b`\n FROM t1_00849\n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849\n ) AS t2_00849 ON `--t1_00849.b` = `--t2_00849.b`\n WHERE `--t1_00849.b` = `--t2_00849.b`\n)\nALL INNER JOIN \n(\n SELECT *\n FROM t3_00849\n) AS t3_00849 ON `--t1_00849.b` = b\nWHERE (`--t1_00849.b` = `--t2_00849.b`) AND (`--t1_00849.b` = b) +SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `--t2_00849.a`, \n `t2_00849.b`, \n a AS `--t3_00849.a`, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849\n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849\n ) AS t2_00849 ON `--t1_00849.a` = `--t2_00849.a`\n WHERE `--t1_00849.a` = `--t2_00849.a`\n )\n ALL INNER JOIN \n (\n SELECT *\n FROM t3_00849\n ) AS t3_00849 ON `--t1_00849.a` = `--t3_00849.a`\n WHERE (`--t1_00849.a` = `--t3_00849.a`) AND (`--t1_00849.a` = `--t2_00849.a`)\n)\nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849\n) AS t4_00849 ON `--t1_00849.a` = a\nWHERE (`--t1_00849.a` = `--t2_00849.a`) AND (`--t1_00849.a` = `--t3_00849.a`) AND (`--t1_00849.a` = a) +SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n `--t1_00849.b`, \n `t2_00849.a`, \n `--t2_00849.b`, \n a, \n b AS `--t3_00849.b`\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b AS `--t1_00849.b`, \n t2_00849.a, \n t2_00849.b AS `--t2_00849.b`\n FROM t1_00849\n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849\n ) AS t2_00849 ON `--t1_00849.b` = `--t2_00849.b`\n WHERE `--t1_00849.b` = `--t2_00849.b`\n )\n ALL INNER JOIN \n (\n SELECT *\n FROM t3_00849\n ) AS t3_00849 ON `--t1_00849.b` = `--t3_00849.b`\n WHERE (`--t1_00849.b` = `--t3_00849.b`) AND (`--t1_00849.b` = `--t2_00849.b`)\n)\nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849\n) AS t4_00849 ON `--t1_00849.b` = b\nWHERE (`--t1_00849.b` = `--t2_00849.b`) AND (`--t1_00849.b` = `--t3_00849.b`) AND (`--t1_00849.b` = b) +SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `--t2_00849.a`, \n `t2_00849.b`, \n a AS `--t3_00849.a`, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849\n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849\n ) AS t2_00849 ON `--t2_00849.a` = `--t1_00849.a`\n WHERE `--t2_00849.a` = `--t1_00849.a`\n )\n ALL INNER JOIN \n (\n SELECT *\n FROM t3_00849\n ) AS t3_00849 ON `--t2_00849.a` = `--t3_00849.a`\n WHERE (`--t2_00849.a` = `--t3_00849.a`) AND (`--t2_00849.a` = `--t1_00849.a`)\n)\nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849\n) AS t4_00849 ON `--t2_00849.a` = a\nWHERE (`--t2_00849.a` = `--t1_00849.a`) AND (`--t2_00849.a` = `--t3_00849.a`) AND (`--t2_00849.a` = a) +SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `--t2_00849.a`, \n `t2_00849.b`, \n a AS `--t3_00849.a`, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849\n CROSS JOIN \n (\n SELECT *\n FROM t2_00849\n ) AS t2_00849\n )\n ALL INNER JOIN \n (\n SELECT *\n FROM t3_00849\n ) AS t3_00849 ON (`--t3_00849.a` = `--t1_00849.a`) AND (`--t3_00849.a` = `--t2_00849.a`)\n WHERE (`--t3_00849.a` = `--t2_00849.a`) AND (`--t3_00849.a` = `--t1_00849.a`)\n)\nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849\n) AS t4_00849 ON `--t3_00849.a` = a\nWHERE (`--t3_00849.a` = `--t1_00849.a`) AND (`--t3_00849.a` = `--t2_00849.a`) AND (`--t3_00849.a` = a) +SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `--t2_00849.a`, \n `t2_00849.b`, \n a AS `--t3_00849.a`, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849\n CROSS JOIN \n (\n SELECT *\n FROM t2_00849\n ) AS t2_00849\n )\n CROSS JOIN \n (\n SELECT *\n FROM t3_00849\n ) AS t3_00849\n)\nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849\n) AS t4_00849 ON (a = `--t1_00849.a`) AND (a = `--t2_00849.a`) AND (a = `--t3_00849.a`)\nWHERE (a = `--t1_00849.a`) AND (a = `--t2_00849.a`) AND (a = `--t3_00849.a`) +SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `--t2_00849.a`, \n `t2_00849.b`, \n a AS `--t3_00849.a`, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849\n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849\n ) AS t2_00849 ON `--t1_00849.a` = `--t2_00849.a`\n WHERE `--t1_00849.a` = `--t2_00849.a`\n )\n ALL INNER JOIN \n (\n SELECT *\n FROM t3_00849\n ) AS t3_00849 ON `--t2_00849.a` = `--t3_00849.a`\n WHERE (`--t2_00849.a` = `--t3_00849.a`) AND (`--t1_00849.a` = `--t2_00849.a`)\n)\nALL INNER JOIN \n(\n SELECT *\n FROM t4_00849\n) AS t4_00849 ON `--t3_00849.a` = a\nWHERE (`--t1_00849.a` = `--t2_00849.a`) AND (`--t2_00849.a` = `--t3_00849.a`) AND (`--t3_00849.a` = a) +SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `t2_00849.a`, \n `t2_00849.b`, \n a, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a, \n t2_00849.b\n FROM t1_00849\n CROSS JOIN \n (\n SELECT *\n FROM t2_00849\n ) AS t2_00849\n )\n CROSS JOIN \n (\n SELECT *\n FROM t3_00849\n ) AS t3_00849\n)\nCROSS JOIN \n(\n SELECT *\n FROM t4_00849\n) AS t4_00849 +SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n `--t1_00849.a`, \n b, \n `t2_00849.a`, \n `t2_00849.b`, \n a, \n t3_00849.b\n FROM \n (\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a, \n t2_00849.b\n FROM t1_00849\n CROSS JOIN \n (\n SELECT *\n FROM t2_00849\n ) AS t2_00849\n )\n CROSS JOIN \n (\n SELECT *\n FROM t3_00849\n ) AS t3_00849\n)\nCROSS JOIN \n(\n SELECT *\n FROM t4_00849\n) AS t4_00849 +SELECT `--t1_00849.a` AS `t1_00849.a`\nFROM \n(\n SELECT \n a AS `--t1_00849.a`, \n b, \n t2_00849.a AS `--t2_00849.a`, \n t2_00849.b\n FROM t1_00849\n ALL INNER JOIN \n (\n SELECT *\n FROM t2_00849\n ) AS t2_00849 ON `--t1_00849.a` = `--t2_00849.a`\n)\nCROSS JOIN \n(\n SELECT *\n FROM t3_00849\n) AS t3_00849 SELECT * FROM t1, t2 1 1 1 1 1 1 1 \N diff --git a/dbms/tests/queries/0_stateless/00853_join_with_nulls_crash.reference b/dbms/tests/queries/0_stateless/00853_join_with_nulls_crash.reference index b6168923b09..c23c6409aa2 100644 --- a/dbms/tests/queries/0_stateless/00853_join_with_nulls_crash.reference +++ b/dbms/tests/queries/0_stateless/00853_join_with_nulls_crash.reference @@ -9,8 +9,11 @@ foo \N 2 0 Nullable(String) Nullable(String) foo 2 0 String Nullable(String) bar bar 1 2 String Nullable(String) test 0 1 String Nullable(String) + \N 0 1 String Nullable(String) bar bar 1 2 String Nullable(String) test 0 1 String Nullable(String) + \N 0 1 String Nullable(String) foo 2 0 String bar 1 2 String test 0 1 String + 0 1 String diff --git a/dbms/tests/queries/0_stateless/00872_t64_bit_codec.reference b/dbms/tests/queries/0_stateless/00872_t64_bit_codec.reference new file mode 100644 index 00000000000..d50f908f921 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00872_t64_bit_codec.reference @@ -0,0 +1,7 @@ +0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 +42 42 42 42 42 42 42 42 +42 42 42 42 42 42 42 42 +42 42 42 42 42 42 42 42 +42 42 42 42 42 42 42 42 diff --git a/dbms/tests/queries/0_stateless/00872_t64_bit_codec.sql b/dbms/tests/queries/0_stateless/00872_t64_bit_codec.sql new file mode 100644 index 00000000000..d173b84def0 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00872_t64_bit_codec.sql @@ -0,0 +1,101 @@ +DROP TABLE IF EXISTS test.t64; + +CREATE TABLE test.t64 +( + u8 UInt8, + t_u8 UInt8 Codec(T64('bit'), LZ4), + u16 UInt16, + t_u16 UInt16 Codec(T64('bit'), LZ4), + u32 UInt32, + t_u32 UInt32 Codec(T64('bit'), LZ4), + u64 UInt64, + t_u64 UInt64 Codec(T64('bit'), LZ4) +) ENGINE MergeTree() ORDER BY tuple(); + +INSERT INTO test.t64 SELECT number AS x, x, x, x, x, x, x, x FROM numbers(1); +INSERT INTO test.t64 SELECT number AS x, x, x, x, x, x, x, x FROM numbers(2); +INSERT INTO test.t64 SELECT 42 AS x, x, x, x, x, x, x, x FROM numbers(4); + +SELECT * FROM test.t64 ORDER BY u64; + +INSERT INTO test.t64 SELECT number AS x, x, x, x, x, x, x, x FROM numbers(intExp2(8)); +INSERT INTO test.t64 SELECT number AS x, x, x, x, x, x, x, x FROM numbers(intExp2(9)); +SELECT * FROM test.t64 WHERE u8 != t_u8; +SELECT * FROM test.t64 WHERE u16 != t_u16; +SELECT * FROM test.t64 WHERE u32 != t_u32; +SELECT * FROM test.t64 WHERE u64 != t_u64; + +INSERT INTO test.t64 SELECT (intExp2(16) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(10); +INSERT INTO test.t64 SELECT (intExp2(16) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(11); +INSERT INTO test.t64 SELECT (intExp2(16) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(64); +INSERT INTO test.t64 SELECT (intExp2(16) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(65); +INSERT INTO test.t64 SELECT (intExp2(16) - 1 + number) AS x, x, x, x, x, x, x, x FROM numbers(65); +SELECT * FROM test.t64 WHERE u8 != t_u8; +SELECT * FROM test.t64 WHERE u16 != t_u16; +SELECT * FROM test.t64 WHERE u32 != t_u32; +SELECT * FROM test.t64 WHERE u64 != t_u64; + +INSERT INTO test.t64 SELECT (intExp2(24) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(10); +INSERT INTO test.t64 SELECT (intExp2(24) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(11); +INSERT INTO test.t64 SELECT (intExp2(24) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(128); +INSERT INTO test.t64 SELECT (intExp2(24) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(129); +INSERT INTO test.t64 SELECT (intExp2(24) - 1 + number) AS x, x, x, x, x, x, x, x FROM numbers(129); +SELECT * FROM test.t64 WHERE u8 != t_u8; +SELECT * FROM test.t64 WHERE u16 != t_u16; +SELECT * FROM test.t64 WHERE u32 != t_u32; +SELECT * FROM test.t64 WHERE u64 != t_u64; + +INSERT INTO test.t64 SELECT (intExp2(32) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(10); +INSERT INTO test.t64 SELECT (intExp2(32) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(20); +INSERT INTO test.t64 SELECT (intExp2(32) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(256); +INSERT INTO test.t64 SELECT (intExp2(32) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(257); +INSERT INTO test.t64 SELECT (intExp2(32) - 1 + number) AS x, x, x, x, x, x, x, x FROM numbers(257); +SELECT * FROM test.t64 WHERE u8 != t_u8; +SELECT * FROM test.t64 WHERE u16 != t_u16; +SELECT * FROM test.t64 WHERE u32 != t_u32; +SELECT * FROM test.t64 WHERE u64 != t_u64; + +INSERT INTO test.t64 SELECT (intExp2(40) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(10); +INSERT INTO test.t64 SELECT (intExp2(40) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(20); +INSERT INTO test.t64 SELECT (intExp2(40) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(512); +INSERT INTO test.t64 SELECT (intExp2(40) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(513); +INSERT INTO test.t64 SELECT (intExp2(40) - 1 + number) AS x, x, x, x, x, x, x, x FROM numbers(513); +SELECT * FROM test.t64 WHERE u8 != t_u8; +SELECT * FROM test.t64 WHERE u16 != t_u16; +SELECT * FROM test.t64 WHERE u32 != t_u32; +SELECT * FROM test.t64 WHERE u64 != t_u64; + +INSERT INTO test.t64 SELECT (intExp2(48) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(10); +INSERT INTO test.t64 SELECT (intExp2(48) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(20); +INSERT INTO test.t64 SELECT (intExp2(48) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(1024); +INSERT INTO test.t64 SELECT (intExp2(48) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(1025); +INSERT INTO test.t64 SELECT (intExp2(48) - 1 + number) AS x, x, x, x, x, x, x, x FROM numbers(1025); +SELECT * FROM test.t64 WHERE u8 != t_u8; +SELECT * FROM test.t64 WHERE u16 != t_u16; +SELECT * FROM test.t64 WHERE u32 != t_u32; +SELECT * FROM test.t64 WHERE u64 != t_u64; + +INSERT INTO test.t64 SELECT (intExp2(56) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(10); +INSERT INTO test.t64 SELECT (intExp2(56) - 10 + number) AS x, x, x, x, x, x, x, x FROM numbers(20); +INSERT INTO test.t64 SELECT (intExp2(56) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(2048); +INSERT INTO test.t64 SELECT (intExp2(56) - 64 + number) AS x, x, x, x, x, x, x, x FROM numbers(2049); +INSERT INTO test.t64 SELECT (intExp2(56) - 1 + number) AS x, x, x, x, x, x, x, x FROM numbers(2049); +SELECT * FROM test.t64 WHERE u8 != t_u8; +SELECT * FROM test.t64 WHERE u16 != t_u16; +SELECT * FROM test.t64 WHERE u32 != t_u32; +SELECT * FROM test.t64 WHERE u64 != t_u64; + +INSERT INTO test.t64 SELECT (intExp2(63) + number * intExp2(62)) AS x, x, x, x, x, x, x, x FROM numbers(10); +SELECT * FROM test.t64 WHERE u8 != t_u8; +SELECT * FROM test.t64 WHERE u16 != t_u16; +SELECT * FROM test.t64 WHERE u32 != t_u32; +SELECT * FROM test.t64 WHERE u64 != t_u64; + +OPTIMIZE TABLE test.t64 FINAL; + +SELECT * FROM test.t64 WHERE u8 != t_u8; +SELECT * FROM test.t64 WHERE u16 != t_u16; +SELECT * FROM test.t64 WHERE u32 != t_u32; +SELECT * FROM test.t64 WHERE u64 != t_u64; + +DROP TABLE test.t64; diff --git a/dbms/tests/queries/0_stateless/00874_issue_3495.reference b/dbms/tests/queries/0_stateless/00874_issue_3495.reference new file mode 100644 index 00000000000..ebb020d8e29 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00874_issue_3495.reference @@ -0,0 +1,6 @@ +1 1.1 1.1 +1 1.2 1.1 +2 2.1 2.1 +1 1.1 1.1 +1 1.2 1.1 +2 2.1 2.1 diff --git a/dbms/tests/queries/0_stateless/00874_issue_3495.sql b/dbms/tests/queries/0_stateless/00874_issue_3495.sql new file mode 100644 index 00000000000..02c70ac7482 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00874_issue_3495.sql @@ -0,0 +1,21 @@ +drop table if exists t; +create table t (a Int8, val Float32) engine = Memory(); +insert into t values (1,1.1), (1,1.2), (2,2.1); + +SET enable_optimize_predicate_expression = 0; + +SELECT * FROM ( + SELECT a, t1.val as val1, t2.val as val2 + FROM t t1 + ANY LEFT JOIN t t2 USING a +) ORDER BY val1; + +SET enable_optimize_predicate_expression = 1; + +SELECT * FROM ( + SELECT a, t1.val as val1, t2.val as val2 + FROM t t1 + ANY LEFT JOIN t t2 USING a +) ORDER BY val1; + +drop table t; diff --git a/dbms/tests/queries/0_stateless/00875_join_right_nulls.reference b/dbms/tests/queries/0_stateless/00875_join_right_nulls.reference new file mode 100644 index 00000000000..01932c3f068 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00875_join_right_nulls.reference @@ -0,0 +1,46 @@ +on +n rj n 1 1 +n rj n id id +n rj n \N \N +n fj n 1 1 +n fj n id id +n fj n \N \N +n fj n \N \N +t rj n \N +t rj n 1 1 +t rj n id id +t fj n \N +t fj n 1 1 +t fj n id id +n rj t 1 1 +n rj t id id +n fj t 1 1 +n fj t id id +n fj t \N \N +using +n rj n 1 1 +n rj n id id +n rj n \N \N +n fj n 1 1 +n fj n id id +n fj n \N \N +n fj n \N \N +t rj n \N +t rj n 1 1 +t rj n id id +t fj n \N +t fj n 1 1 +t fj n id id +n rj t 1 1 +n rj t id id +n fj t 1 1 +n fj t id id +n fj t \N \N +0 2 +1001 2 +1001 2 +2002 2 +0 2 +1001 2 +1001 2 +2002 2 diff --git a/dbms/tests/queries/0_stateless/00875_join_right_nulls.sql b/dbms/tests/queries/0_stateless/00875_join_right_nulls.sql new file mode 100644 index 00000000000..288a3043569 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00875_join_right_nulls.sql @@ -0,0 +1,48 @@ +DROP TABLE IF EXISTS t; +DROP TABLE IF EXISTS nt; + +CREATE TABLE t (x String) ENGINE = Memory; +CREATE TABLE nt (x Nullable(String)) ENGINE = Memory; + +INSERT INTO t (x) VALUES ('id'), ('1'); +INSERT INTO nt (x) VALUES ('id'), (NULL), ('1'); + +SET join_use_nulls = 1; + +SELECT 'on'; + +SELECT 'n rj n', t1.x, t2.x FROM nt AS t1 RIGHT JOIN nt AS t2 ON t1.x = t2.x ORDER BY t1.x; +SELECT 'n fj n', t1.x, t2.x FROM nt AS t1 FULL JOIN nt AS t2 ON t1.x = t2.x ORDER BY t1.x; + +SELECT 't rj n', t1.x, t2.x FROM t AS t1 RIGHT JOIN nt AS t2 ON t1.x = t2.x ORDER BY t1.x; +SELECT 't fj n', t1.x, t2.x FROM t AS t1 FULL JOIN nt AS t2 ON t1.x = t2.x ORDER BY t1.x; + +SELECT 'n rj t', t1.x, t2.x FROM nt AS t1 RIGHT JOIN t AS t2 ON t1.x = t2.x ORDER BY t1.x; +SELECT 'n fj t', t1.x, t2.x FROM nt AS t1 FULL JOIN t AS t2 ON t1.x = t2.x ORDER BY t1.x; + +SELECT 'using'; + +SELECT 'n rj n', t1.x, t2.x FROM nt AS t1 RIGHT JOIN nt AS t2 USING(x) ORDER BY t1.x; +SELECT 'n fj n', t1.x, t2.x FROM nt AS t1 FULL JOIN nt AS t2 USING(x) ORDER BY t1.x; + +SELECT 't rj n', t1.x, t2.x FROM t AS t1 RIGHT JOIN nt AS t2 USING(x) ORDER BY t1.x; +SELECT 't fj n', t1.x, t2.x FROM t AS t1 FULL JOIN nt AS t2 USING(x) ORDER BY t1.x; + +SELECT 'n rj t', t1.x, t2.x FROM nt AS t1 RIGHT JOIN t AS t2 USING(x) ORDER BY t1.x; +SELECT 'n fj t', t1.x, t2.x FROM nt AS t1 FULL JOIN t AS t2 USING(x) ORDER BY t1.x; + + +INSERT INTO nt (x) SELECT NULL as x FROM numbers(1000); + +SELECT sum(isNull(t1.x)), count(t1.x) FROM nt AS t1 INNER JOIN nt AS t2 ON t1.x = t2.x; +SELECT sum(isNull(t1.x)), count(t1.x) FROM nt AS t1 LEFT JOIN nt AS t2 ON t1.x = t2.x; +SELECT sum(isNull(t1.x)), count(t1.x) FROM nt AS t1 RIGHT JOIN nt AS t2 ON t1.x = t2.x; +SELECT sum(isNull(t1.x)), count(t1.x) FROM nt AS t1 FULL JOIN nt AS t2 ON t1.x = t2.x; + +SELECT sum(isNull(t1.x)), count(t1.x) FROM nt AS t1 INNER JOIN nt AS t2 USING(x); +SELECT sum(isNull(t1.x)), count(t1.x) FROM nt AS t1 LEFT JOIN nt AS t2 USING(x); +SELECT sum(isNull(t1.x)), count(t1.x) FROM nt AS t1 RIGHT JOIN nt AS t2 USING(x); +SELECT sum(isNull(t1.x)), count(t1.x) FROM nt AS t1 FULL JOIN nt AS t2 USING(x); + +DROP TABLE t; +DROP TABLE nt; diff --git a/dbms/tests/queries/0_stateless/00876_wrong_arraj_join_column.reference b/dbms/tests/queries/0_stateless/00876_wrong_arraj_join_column.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dbms/tests/queries/0_stateless/00876_wrong_arraj_join_column.sql b/dbms/tests/queries/0_stateless/00876_wrong_arraj_join_column.sql new file mode 100644 index 00000000000..0e72f9a67ce --- /dev/null +++ b/dbms/tests/queries/0_stateless/00876_wrong_arraj_join_column.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS visits; +CREATE TABLE visits (str String) ENGINE = MergeTree ORDER BY (str); + +SELECT 1 +FROM visits +ARRAY JOIN arrayFilter(t -> 1, arrayMap(x -> tuple(x), [42])) AS i +WHERE ((str, i.1) IN ('x', 0)); + +DROP TABLE visits; diff --git a/dbms/tests/queries/0_stateless/00898_quantile_timing_parameter_check.reference b/dbms/tests/queries/0_stateless/00898_quantile_timing_parameter_check.reference index 7ed6ff82de6..47586a86a32 100644 --- a/dbms/tests/queries/0_stateless/00898_quantile_timing_parameter_check.reference +++ b/dbms/tests/queries/0_stateless/00898_quantile_timing_parameter_check.reference @@ -1 +1,2 @@ 5 +2 diff --git a/dbms/tests/queries/0_stateless/00898_quantile_timing_parameter_check.sql b/dbms/tests/queries/0_stateless/00898_quantile_timing_parameter_check.sql index 8279804a22c..ce1f3e897d3 100644 --- a/dbms/tests/queries/0_stateless/00898_quantile_timing_parameter_check.sql +++ b/dbms/tests/queries/0_stateless/00898_quantile_timing_parameter_check.sql @@ -1,2 +1,2 @@ SELECT quantileTiming(0.5)(number) FROM numbers(10); -SELECT quantileTiming(0.5)(number / 2) FROM numbers(10); -- { serverError 43 } +SELECT quantileTiming(0.5)(number / 2) FROM numbers(10); diff --git a/dbms/tests/queries/0_stateless/00908_analyze_query.reference b/dbms/tests/queries/0_stateless/00908_analyze_query.reference index a10c36ca4dd..a8619cfcd4b 100644 --- a/dbms/tests/queries/0_stateless/00908_analyze_query.reference +++ b/dbms/tests/queries/0_stateless/00908_analyze_query.reference @@ -1 +1 @@ -SELECT \n a, \n b\nFROM a +SELECT \n a, \n b\nFROM a diff --git a/dbms/tests/queries/0_stateless/00909_kill_not_initialized_query.sh b/dbms/tests/queries/0_stateless/00909_kill_not_initialized_query.sh index d8a4f29b30f..67454f676b3 100755 --- a/dbms/tests/queries/0_stateless/00909_kill_not_initialized_query.sh +++ b/dbms/tests/queries/0_stateless/00909_kill_not_initialized_query.sh @@ -11,7 +11,7 @@ $CLICKHOUSE_CLIENT -q "CREATE TABLE cannot_kill_query (x UInt64) ENGINE = MergeT $CLICKHOUSE_CLIENT -q "INSERT INTO cannot_kill_query SELECT * FROM numbers(10000000)" &> /dev/null # This SELECT query will run for a long time. It's used as bloker for ALTER query. It will be killed with SYNC kill. -query_for_pending="SELECT count() FROM cannot_kill_query WHERE NOT ignore(sleep(1)) SETTINGS max_threads=1, max_block_size=1" +query_for_pending="SELECT count() FROM cannot_kill_query WHERE NOT ignore(sleep(1)) SETTINGS max_threads = 1, max_block_size = 1" $CLICKHOUSE_CLIENT -q "$query_for_pending" &>/dev/null & sleep 1 # queries should be in strict order @@ -23,7 +23,7 @@ sleep 1 # This SELECT query will also run for a long time. Also it's blocked by ALTER query. It will be killed with ASYNC kill. # This is main idea which we check -- blocked queries can be killed with ASYNC kill. -query_to_kill="SELECT sum(1) FROM cannot_kill_query WHERE NOT ignore(sleep(1)) SETTINGS max_threads=1" +query_to_kill="SELECT sum(1) FROM cannot_kill_query WHERE NOT ignore(sleep(1)) SETTINGS max_threads = 1" $CLICKHOUSE_CLIENT -q "$query_to_kill" &>/dev/null & sleep 1 # just to be sure that kill of $query_to_kill will be executed after $query_to_kill. diff --git a/dbms/tests/queries/0_stateless/00910_client_window_size_detection.reference b/dbms/tests/queries/0_stateless/00910_client_window_size_detection.reference index 85322d0b541..f96ac067218 100644 --- a/dbms/tests/queries/0_stateless/00910_client_window_size_detection.reference +++ b/dbms/tests/queries/0_stateless/00910_client_window_size_detection.reference @@ -1 +1 @@ -79 +105 diff --git a/dbms/tests/queries/0_stateless/00916_create_or_replace_view.reference b/dbms/tests/queries/0_stateless/00916_create_or_replace_view.reference index a0313be86ff..30d14bf1e41 100644 --- a/dbms/tests/queries/0_stateless/00916_create_or_replace_view.reference +++ b/dbms/tests/queries/0_stateless/00916_create_or_replace_view.reference @@ -1,2 +1,2 @@ -CREATE VIEW default.t (`number` UInt64) AS SELECT number FROM system.numbers -CREATE VIEW default.t (`next_number` UInt64) AS SELECT number + 1 AS next_number FROM system.numbers +CREATE VIEW default.t (`number` UInt64) AS SELECT number FROM system.numbers +CREATE VIEW default.t (`next_number` UInt64) AS SELECT number + 1 AS next_number FROM system.numbers diff --git a/dbms/tests/queries/0_stateless/00918_json_functions.reference b/dbms/tests/queries/0_stateless/00918_json_functions.reference index 631d421b66f..44d4dc1c9bf 100644 --- a/dbms/tests/queries/0_stateless/00918_json_functions.reference +++ b/dbms/tests/queries/0_stateless/00918_json_functions.reference @@ -1,3 +1,79 @@ +--allow_simdjson=1-- +--JSONLength-- +2 +3 +0 +--JSONHas-- +1 +1 +0 +--JSONKey-- +a +b +b +a +--JSONType-- +Object +Array +--JSONExtract-- +-100 +200 +300 +1 +0 +--JSONExtractString-- +hello +hello +\n\0 +☺ + + +--JSONExtract (generic)-- +('hello',[-100,200,300]) +('hello',[-100,200,300]) +([-100,200,300],'hello') +('hello\0',0) +hello +[-100,200,300] +(-100,200,300) +[-100,0,0] +[-100,NULL,NULL] +[0,200,0] +[NULL,200,NULL] +-100 +200 +\N +1 +Thursday +Friday +--JSONExtractKeysAndValues-- +[('a','hello')] +[('b',[-100,200,300])] +[('a','hello'),('b','world')] +[('a',5),('b',7),('c',11)] +--JSONExtractRaw-- +{"a":"hello","b":[-100,200,300]} +"hello" +[-100,200,300] +-100 +{"a":"hello","b":[-100,200,300],"c":{"d":[121,144]}} +{"d":[121,144]} +[121,144] +144 + +{"passed":true} +{} +"\\n\\u0000" +"☺" +--const/non-const mixed-- +a +b +c +d +e +u +v +--allow_simdjson=0-- --JSONLength-- 2 3 diff --git a/dbms/tests/queries/0_stateless/00918_json_functions.sql b/dbms/tests/queries/0_stateless/00918_json_functions.sql index 1a9ce2bbc11..83f6d1578f9 100644 --- a/dbms/tests/queries/0_stateless/00918_json_functions.sql +++ b/dbms/tests/queries/0_stateless/00918_json_functions.sql @@ -1,3 +1,4 @@ +SELECT '--allow_simdjson=1--'; SET allow_simdjson=1; SELECT '--JSONLength--'; @@ -78,3 +79,87 @@ SELECT JSONExtractRaw('{"abc":"\\u263a"}', 'abc'); SELECT '--const/non-const mixed--'; SELECT JSONExtractString('["a", "b", "c", "d", "e"]', idx) FROM (SELECT arrayJoin([1,2,3,4,5]) AS idx); SELECT JSONExtractString(json, 's') FROM (SELECT arrayJoin(['{"s":"u"}', '{"s":"v"}']) AS json); + + + +SELECT '--allow_simdjson=0--'; +SET allow_simdjson=0; + +SELECT '--JSONLength--'; +SELECT JSONLength('{"a": "hello", "b": [-100, 200.0, 300]}'); +SELECT JSONLength('{"a": "hello", "b": [-100, 200.0, 300]}', 'b'); +SELECT JSONLength('{}'); + +SELECT '--JSONHas--'; +SELECT JSONHas('{"a": "hello", "b": [-100, 200.0, 300]}', 'a'); +SELECT JSONHas('{"a": "hello", "b": [-100, 200.0, 300]}', 'b'); +SELECT JSONHas('{"a": "hello", "b": [-100, 200.0, 300]}', 'c'); + +SELECT '--JSONKey--'; +SELECT JSONKey('{"a": "hello", "b": [-100, 200.0, 300]}', 1); +SELECT JSONKey('{"a": "hello", "b": [-100, 200.0, 300]}', 2); +SELECT JSONKey('{"a": "hello", "b": [-100, 200.0, 300]}', -1); +SELECT JSONKey('{"a": "hello", "b": [-100, 200.0, 300]}', -2); + +SELECT '--JSONType--'; +SELECT JSONType('{"a": "hello", "b": [-100, 200.0, 300]}'); +SELECT JSONType('{"a": "hello", "b": [-100, 200.0, 300]}', 'b'); + +SELECT '--JSONExtract--'; +SELECT JSONExtractInt('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 1); +SELECT JSONExtractFloat('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 2); +SELECT JSONExtractUInt('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', -1); +SELECT JSONExtractBool('{"passed": true}', 'passed'); +SELECT JSONExtractBool('"HX-='); + +SELECT '--JSONExtractString--'; +SELECT JSONExtractString('{"a": "hello", "b": [-100, 200.0, 300]}', 'a'); +SELECT JSONExtractString('{"a": "hello", "b": [-100, 200.0, 300]}', 1); +select JSONExtractString('{"abc":"\\n\\u0000"}', 'abc'); +select JSONExtractString('{"abc":"\\u263a"}', 'abc'); +select JSONExtractString('{"abc":"\\u263"}', 'abc'); +select JSONExtractString('{"abc":"hello}', 'abc'); + +SELECT '--JSONExtract (generic)--'; +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'Tuple(String, Array(Float64))'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'Tuple(a String, b Array(Float64))'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'Tuple(b Array(Float64), a String)'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'Tuple(a FixedString(6), c UInt8)'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'a', 'String'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 'Array(Float32)'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 'Tuple(Int8, Float32, UInt16)'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 'Array(Int8)'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 'Array(Nullable(Int8))'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 'Array(UInt8)'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 'Array(Nullable(UInt8))'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 1, 'Int8'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 2, 'Int32'); +SELECT JSONExtract('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 4, 'Nullable(Int64)'); +SELECT JSONExtract('{"passed": true}', 'passed', 'UInt8'); +SELECT JSONExtract('{"day": "Thursday"}', 'day', 'Enum8(\'Sunday\' = 0, \'Monday\' = 1, \'Tuesday\' = 2, \'Wednesday\' = 3, \'Thursday\' = 4, \'Friday\' = 5, \'Saturday\' = 6)'); +SELECT JSONExtract('{"day": 5}', 'day', 'Enum8(\'Sunday\' = 0, \'Monday\' = 1, \'Tuesday\' = 2, \'Wednesday\' = 3, \'Thursday\' = 4, \'Friday\' = 5, \'Saturday\' = 6)'); + +SELECT '--JSONExtractKeysAndValues--'; +SELECT JSONExtractKeysAndValues('{"a": "hello", "b": [-100, 200.0, 300]}', 'String'); +SELECT JSONExtractKeysAndValues('{"a": "hello", "b": [-100, 200.0, 300]}', 'Array(Float64)'); +SELECT JSONExtractKeysAndValues('{"a": "hello", "b": "world"}', 'String'); +SELECT JSONExtractKeysAndValues('{"x": {"a": 5, "b": 7, "c": 11}}', 'x', 'Int8'); + +SELECT '--JSONExtractRaw--'; +SELECT JSONExtractRaw('{"a": "hello", "b": [-100, 200.0, 300]}'); +SELECT JSONExtractRaw('{"a": "hello", "b": [-100, 200.0, 300]}', 'a'); +SELECT JSONExtractRaw('{"a": "hello", "b": [-100, 200.0, 300]}', 'b'); +SELECT JSONExtractRaw('{"a": "hello", "b": [-100, 200.0, 300]}', 'b', 1); +SELECT JSONExtractRaw('{"a": "hello", "b": [-100, 200.0, 300], "c":{"d":[121,144]}}'); +SELECT JSONExtractRaw('{"a": "hello", "b": [-100, 200.0, 300], "c":{"d":[121,144]}}', 'c'); +SELECT JSONExtractRaw('{"a": "hello", "b": [-100, 200.0, 300], "c":{"d":[121,144]}}', 'c', 'd'); +SELECT JSONExtractRaw('{"a": "hello", "b": [-100, 200.0, 300], "c":{"d":[121,144]}}', 'c', 'd', 2); +SELECT JSONExtractRaw('{"a": "hello", "b": [-100, 200.0, 300], "c":{"d":[121,144]}}', 'c', 'd', 3); +SELECT JSONExtractRaw('{"passed": true}'); +SELECT JSONExtractRaw('{}'); +SELECT JSONExtractRaw('{"abc":"\\n\\u0000"}', 'abc'); +SELECT JSONExtractRaw('{"abc":"\\u263a"}', 'abc'); + +SELECT '--const/non-const mixed--'; +SELECT JSONExtractString('["a", "b", "c", "d", "e"]', idx) FROM (SELECT arrayJoin([1,2,3,4,5]) AS idx); +SELECT JSONExtractString(json, 's') FROM (SELECT arrayJoin(['{"s":"u"}', '{"s":"v"}']) AS json); diff --git a/dbms/tests/queries/0_stateless/00926_geo_to_h3.reference b/dbms/tests/queries/0_stateless/00926_geo_to_h3.reference new file mode 100644 index 00000000000..ad594f0e81f --- /dev/null +++ b/dbms/tests/queries/0_stateless/00926_geo_to_h3.reference @@ -0,0 +1,20 @@ +644325529094369568 +639821928864584823 +644325528491955313 +644325528491955313 +644325528627451570 +644325529094369568 +644325528491955313 +644325528491955313 +644325528491955313 +644325528627451570 +644325529094369568 +55.720762 37.598135 644325528491955313 +55.720762 37.598135 644325528491955313 +55.72076201 37.598135 644325528491955313 +55.763241 37.660183 644325528627451570 +55.77922738 37.63098076 644325529094369568 +639821928864584823 1 +644325528491955313 2 +644325528627451570 1 +644325529094369568 1 diff --git a/dbms/tests/queries/0_stateless/00926_geo_to_h3.sql b/dbms/tests/queries/0_stateless/00926_geo_to_h3.sql new file mode 100644 index 00000000000..d3ce898c56a --- /dev/null +++ b/dbms/tests/queries/0_stateless/00926_geo_to_h3.sql @@ -0,0 +1,19 @@ +USE test; + +DROP TABLE IF EXISTS table1; + +CREATE TABLE table1 (lat Float64, lon Float64, resolution UInt8) ENGINE = Memory; + +INSERT INTO table1 VALUES(55.77922738, 37.63098076, 15); +INSERT INTO table1 VALUES(55.76324100, 37.66018300, 15); +INSERT INTO table1 VALUES(55.72076200, 37.59813500, 15); +INSERT INTO table1 VALUES(55.72076201, 37.59813500, 15); +INSERT INTO table1 VALUES(55.72076200, 37.59813500, 14); + +select geoToH3(37.63098076, 55.77922738, 15); +select geoToH3(lon, lat, resolution) from table1 order by lat, lon, resolution; +select geoToH3(lon, lat, 15) AS k from table1 order by lat, lon, k; +select lat, lon, geoToH3(lon, lat, 15) AS k from table1 order by lat, lon, k; +select geoToH3(lon, lat, resolution) AS k, count(*) from table1 group by k order by k; + +DROP TABLE table1 diff --git a/dbms/tests/queries/0_stateless/00933_ttl_simple.reference b/dbms/tests/queries/0_stateless/00933_ttl_simple.reference index f1377e3d220..09e5d7d1f02 100644 --- a/dbms/tests/queries/0_stateless/00933_ttl_simple.reference +++ b/dbms/tests/queries/0_stateless/00933_ttl_simple.reference @@ -1,5 +1,6 @@ 0 0 0 0 +5 6 2000-10-10 00:00:00 0 2000-10-10 00:00:00 0 2000-10-10 00:00:00 0 diff --git a/dbms/tests/queries/0_stateless/00933_ttl_simple.sql b/dbms/tests/queries/0_stateless/00933_ttl_simple.sql index 62b320cc0b0..11f0055a377 100644 --- a/dbms/tests/queries/0_stateless/00933_ttl_simple.sql +++ b/dbms/tests/queries/0_stateless/00933_ttl_simple.sql @@ -9,6 +9,17 @@ select a, b from ttl_00933_1; drop table if exists ttl_00933_1; +create table ttl_00933_1 (d DateTime, a Int, b Int) engine = MergeTree order by toDate(d) partition by tuple() ttl d + interval 1 second; +insert into ttl_00933_1 values (now(), 1, 2); +insert into ttl_00933_1 values (now(), 3, 4); +insert into ttl_00933_1 values (now() + 1000, 5, 6); +optimize table ttl_00933_1 final; -- check ttl merge for part with both expired and unexpired values +select sleep(1.1) format Null; -- wait if very fast merge happen +optimize table ttl_00933_1 final; +select a, b from ttl_00933_1; + +drop table if exists ttl_00933_1; + create table ttl_00933_1 (d DateTime, a Int ttl d + interval 1 DAY) engine = MergeTree order by tuple() partition by toDayOfMonth(d); insert into ttl_00933_1 values (toDateTime('2000-10-10 00:00:00'), 1); insert into ttl_00933_1 values (toDateTime('2000-10-10 00:00:00'), 2); diff --git a/dbms/tests/queries/0_stateless/00941_to_custom_week.reference b/dbms/tests/queries/0_stateless/00941_to_custom_week.reference new file mode 100644 index 00000000000..6171bc3937f --- /dev/null +++ b/dbms/tests/queries/0_stateless/00941_to_custom_week.reference @@ -0,0 +1,73 @@ +0 0 1 1 +52 52 53 53 +1 0 +198153 198153 198252 198252 +198701 198652 +0 0 0 0 0 0 1 +1 0 1 1 1 1 1 +0 1 1 1 1 0 0 +1 1 1 2 2 1 1 +199952 200053 200152 200252 200352 200452 200601 +200001 200053 200201 200301 200401 200501 200601 +199952 200101 200201 200301 200401 200453 200552 +200001 200101 200201 200302 200402 200501 200601 +52 53 52 52 +53 52 +52 53 52 53 52 52 52 52 +0 0 52 52 0 0 52 52 +1 1 1 1 1 1 1 1 +53 52 53 52 53 52 1 52 +0 1 53 1 1 1 1 1 +200053 200052 200053 200052 200101 200052 200101 200052 +2016-12-21 52 52 201652 201652 +2016-12-22 52 52 201652 201652 +2016-12-23 52 52 201652 201652 +2016-12-24 52 52 201652 201652 +2016-12-25 53 52 201653 201652 +2016-12-26 53 1 201653 201701 +2016-12-27 53 1 201653 201701 +2016-12-28 53 1 201653 201701 +2016-12-29 53 1 201653 201701 +2016-12-30 53 1 201653 201701 +2016-12-31 53 1 201653 201701 +2017-01-01 1 1 201701 201701 +2017-01-02 1 2 201701 201702 +2017-01-03 1 2 201701 201702 +2017-01-04 1 2 201701 201702 +2017-01-05 1 2 201701 201702 +2017-01-06 1 2 201701 201702 +2017-01-07 1 2 201701 201702 +2017-01-08 2 2 201702 201702 +2017-01-09 2 3 201702 201703 +2017-01-10 2 3 201702 201703 +2016-12-22 00:00:00 52 52 201652 201652 +2016-12-23 00:00:00 52 52 201652 201652 +2016-12-24 00:00:00 52 52 201652 201652 +2016-12-25 00:00:00 53 52 201653 201652 +2016-12-26 00:00:00 53 1 201653 201701 +2016-12-27 00:00:00 53 1 201653 201701 +2016-12-28 00:00:00 53 1 201653 201701 +2016-12-29 00:00:00 53 1 201653 201701 +2016-12-30 00:00:00 53 1 201653 201701 +2016-12-31 00:00:00 53 1 201653 201701 +2017-01-01 00:00:00 1 1 201701 201701 +2017-01-02 00:00:00 1 2 201701 201702 +2017-01-03 00:00:00 1 2 201701 201702 +2017-01-04 00:00:00 1 2 201701 201702 +2017-01-05 00:00:00 1 2 201701 201702 +2017-01-06 00:00:00 1 2 201701 201702 +2017-01-07 00:00:00 1 2 201701 201702 +2017-01-08 00:00:00 2 2 201702 201702 +2017-01-09 00:00:00 2 3 201702 201703 +2017-01-10 00:00:00 2 3 201702 201703 +2017-01-11 00:00:00 2 3 201702 201703 +2018-12-25 2018-12-25 00:00:00 2018-12-23 2018-12-23 2018-12-24 2018-12-24 +2018-12-26 2018-12-26 00:00:00 2018-12-23 2018-12-23 2018-12-24 2018-12-24 +2018-12-27 2018-12-27 00:00:00 2018-12-23 2018-12-23 2018-12-24 2018-12-24 +2018-12-28 2018-12-28 00:00:00 2018-12-23 2018-12-23 2018-12-24 2018-12-24 +2018-12-29 2018-12-29 00:00:00 2018-12-23 2018-12-23 2018-12-24 2018-12-24 +2018-12-30 2018-12-30 00:00:00 2018-12-30 2018-12-30 2018-12-24 2018-12-24 +2018-12-31 2018-12-31 00:00:00 2018-12-30 2018-12-30 2018-12-31 2018-12-31 +2019-01-01 2019-01-01 00:00:00 2018-12-30 2018-12-30 2018-12-31 2018-12-31 +2019-01-02 2019-01-02 00:00:00 2018-12-30 2018-12-30 2018-12-31 2018-12-31 +2019-01-03 2019-01-03 00:00:00 2018-12-30 2018-12-30 2018-12-31 2018-12-31 diff --git a/dbms/tests/queries/0_stateless/00941_to_custom_week.sql b/dbms/tests/queries/0_stateless/00941_to_custom_week.sql new file mode 100644 index 00000000000..a6ff40a6d3f --- /dev/null +++ b/dbms/tests/queries/0_stateless/00941_to_custom_week.sql @@ -0,0 +1,52 @@ +-- week mode [0,7], week test case. refer to the mysql test case +SELECT toWeek(toDate('1998-01-01')), toWeek(toDate('1997-01-01')), toWeek(toDate('1998-01-01'), 1), toWeek(toDate('1997-01-01'), 1); +SELECT toWeek(toDate('1998-12-31')), toWeek(toDate('1997-12-31')), toWeek(toDate('1998-12-31'), 1), toWeek(toDate('1997-12-31'), 1); +SELECT toWeek(toDate('1995-01-01')), toWeek(toDate('1995-01-01'), 1); +SELECT toYearWeek(toDate('1981-12-31'), 1), toYearWeek(toDate('1982-01-01'), 1), toYearWeek(toDate('1982-12-31'), 1), toYearWeek(toDate('1983-01-01'), 1); +SELECT toYearWeek(toDate('1987-01-01'), 1), toYearWeek(toDate('1987-01-01')); + +SELECT toWeek(toDate('2000-01-01'),0) AS w2000, toWeek(toDate('2001-01-01'),0) AS w2001, toWeek(toDate('2002-01-01'),0) AS w2002,toWeek(toDate('2003-01-01'),0) AS w2003, toWeek(toDate('2004-01-01'),0) AS w2004, toWeek(toDate('2005-01-01'),0) AS w2005, toWeek(toDate('2006-01-01'),0) AS w2006; +SELECT toWeek(toDate('2000-01-06'),0) AS w2000, toWeek(toDate('2001-01-06'),0) AS w2001, toWeek(toDate('2002-01-06'),0) AS w2002,toWeek(toDate('2003-01-06'),0) AS w2003, toWeek(toDate('2004-01-06'),0) AS w2004, toWeek(toDate('2005-01-06'),0) AS w2005, toWeek(toDate('2006-01-06'),0) AS w2006; +SELECT toWeek(toDate('2000-01-01'),1) AS w2000, toWeek(toDate('2001-01-01'),1) AS w2001, toWeek(toDate('2002-01-01'),1) AS w2002,toWeek(toDate('2003-01-01'),1) AS w2003, toWeek(toDate('2004-01-01'),1) AS w2004, toWeek(toDate('2005-01-01'),1) AS w2005, toWeek(toDate('2006-01-01'),1) AS w2006; +SELECT toWeek(toDate('2000-01-06'),1) AS w2000, toWeek(toDate('2001-01-06'),1) AS w2001, toWeek(toDate('2002-01-06'),1) AS w2002,toWeek(toDate('2003-01-06'),1) AS w2003, toWeek(toDate('2004-01-06'),1) AS w2004, toWeek(toDate('2005-01-06'),1) AS w2005, toWeek(toDate('2006-01-06'),1) AS w2006; +SELECT toYearWeek(toDate('2000-01-01'),0) AS w2000, toYearWeek(toDate('2001-01-01'),0) AS w2001, toYearWeek(toDate('2002-01-01'),0) AS w2002,toYearWeek(toDate('2003-01-01'),0) AS w2003, toYearWeek(toDate('2004-01-01'),0) AS w2004, toYearWeek(toDate('2005-01-01'),0) AS w2005, toYearWeek(toDate('2006-01-01'),0) AS w2006; +SELECT toYearWeek(toDate('2000-01-06'),0) AS w2000, toYearWeek(toDate('2001-01-06'),0) AS w2001, toYearWeek(toDate('2002-01-06'),0) AS w2002,toYearWeek(toDate('2003-01-06'),0) AS w2003, toYearWeek(toDate('2004-01-06'),0) AS w2004, toYearWeek(toDate('2005-01-06'),0) AS w2005, toYearWeek(toDate('2006-01-06'),0) AS w2006; +SELECT toYearWeek(toDate('2000-01-01'),1) AS w2000, toYearWeek(toDate('2001-01-01'),1) AS w2001, toYearWeek(toDate('2002-01-01'),1) AS w2002,toYearWeek(toDate('2003-01-01'),1) AS w2003, toYearWeek(toDate('2004-01-01'),1) AS w2004, toYearWeek(toDate('2005-01-01'),1) AS w2005, toYearWeek(toDate('2006-01-01'),1) AS w2006; +SELECT toYearWeek(toDate('2000-01-06'),1) AS w2000, toYearWeek(toDate('2001-01-06'),1) AS w2001, toYearWeek(toDate('2002-01-06'),1) AS w2002,toYearWeek(toDate('2003-01-06'),1) AS w2003, toYearWeek(toDate('2004-01-06'),1) AS w2004, toYearWeek(toDate('2005-01-06'),1) AS w2005, toYearWeek(toDate('2006-01-06'),1) AS w2006; +SELECT toWeek(toDate('1998-12-31'),2),toWeek(toDate('1998-12-31'),3), toWeek(toDate('2000-01-01'),2), toWeek(toDate('2000-01-01'),3); +SELECT toWeek(toDate('2000-12-31'),2),toWeek(toDate('2000-12-31'),3); + +SELECT toWeek(toDate('1998-12-31'),0) AS w0, toWeek(toDate('1998-12-31'),1) AS w1, toWeek(toDate('1998-12-31'),2) AS w2, toWeek(toDate('1998-12-31'),3) AS w3, toWeek(toDate('1998-12-31'),4) AS w4, toWeek(toDate('1998-12-31'),5) AS w5, toWeek(toDate('1998-12-31'),6) AS w6, toWeek(toDate('1998-12-31'),7) AS w7; +SELECT toWeek(toDate('2000-01-01'),0) AS w0, toWeek(toDate('2000-01-01'),1) AS w1, toWeek(toDate('2000-01-01'),2) AS w2, toWeek(toDate('2000-01-01'),3) AS w3, toWeek(toDate('2000-01-01'),4) AS w4, toWeek(toDate('2000-01-01'),5) AS w5, toWeek(toDate('2000-01-01'),6) AS w6, toWeek(toDate('2000-01-01'),7) AS w7; +SELECT toWeek(toDate('2000-01-06'),0) AS w0, toWeek(toDate('2000-01-06'),1) AS w1, toWeek(toDate('2000-01-06'),2) AS w2, toWeek(toDate('2000-01-06'),3) AS w3, toWeek(toDate('2000-01-06'),4) AS w4, toWeek(toDate('2000-01-06'),5) AS w5, toWeek(toDate('2000-01-06'),6) AS w6, toWeek(toDate('2000-01-06'),7) AS w7; +SELECT toWeek(toDate('2000-12-31'),0) AS w0, toWeek(toDate('2000-12-31'),1) AS w1, toWeek(toDate('2000-12-31'),2) AS w2, toWeek(toDate('2000-12-31'),3) AS w3, toWeek(toDate('2000-12-31'),4) AS w4, toWeek(toDate('2000-12-31'),5) AS w5, toWeek(toDate('2000-12-31'),6) AS w6, toWeek(toDate('2000-12-31'),7) AS w7; +SELECT toWeek(toDate('2001-01-01'),0) AS w0, toWeek(toDate('2001-01-01'),1) AS w1, toWeek(toDate('2001-01-01'),2) AS w2, toWeek(toDate('2001-01-01'),3) AS w3, toWeek(toDate('2001-01-01'),4) AS w4, toWeek(toDate('2001-01-01'),5) AS w5, toWeek(toDate('2001-01-01'),6) AS w6, toWeek(toDate('2001-01-01'),7) AS w7; + +SELECT toYearWeek(toDate('2000-12-31'),0), toYearWeek(toDate('2000-12-31'),1), toYearWeek(toDate('2000-12-31'),2), toYearWeek(toDate('2000-12-31'),3), toYearWeek(toDate('2000-12-31'),4), toYearWeek(toDate('2000-12-31'),5), toYearWeek(toDate('2000-12-31'),6), toYearWeek(toDate('2000-12-31'),7); + +-- week mode 8,9 +SELECT + toDate('2016-12-21') + number AS d, + toWeek(d, 8) AS week8, + toWeek(d, 9) AS week9, + toYearWeek(d, 8) AS yearWeek8, + toYearWeek(d, 9) AS yearWeek9 +FROM numbers(21); + +SELECT toDateTime(toDate('2016-12-22') + number, 'Europe/Moscow' ) AS d, + toWeek(d, 8, 'Europe/Moscow') AS week8, + toWeek(d, 9, 'Europe/Moscow') AS week9, + toYearWeek(d, 8, 'Europe/Moscow') AS yearWeek8, + toYearWeek(d, 9, 'Europe/Moscow') AS yearWeek9 +FROM numbers(21); + +-- toStartOfWeek +SELECT + toDate('2018-12-25') + number AS x, + toDateTime(x) AS x_t, + toStartOfWeek(x) AS w0, + toStartOfWeek(x_t) AS wt0, + toStartOfWeek(x, 3) AS w3, + toStartOfWeek(x_t, 3) AS wt3 +FROM numbers(10); + diff --git a/dbms/tests/queries/0_stateless/00944_create_bloom_filter_index_with_merge_tree.reference b/dbms/tests/queries/0_stateless/00944_create_bloom_filter_index_with_merge_tree.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dbms/tests/queries/0_stateless/00944_create_bloom_filter_index_with_merge_tree.sh b/dbms/tests/queries/0_stateless/00944_create_bloom_filter_index_with_merge_tree.sh new file mode 100755 index 00000000000..52246b50b7a --- /dev/null +++ b/dbms/tests/queries/0_stateless/00944_create_bloom_filter_index_with_merge_tree.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +. $CURDIR/../shell_config.sh + +set -e + +for sequence in 1 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000; do \ +rate=`echo "1 $sequence" | awk '{printf("%0.9f\n",$1/$2)}'` +$CLICKHOUSE_CLIENT --query="DROP TABLE IF EXISTS test.bloom_filter_idx"; +$CLICKHOUSE_CLIENT --allow_experimental_data_skipping_indices=1 --query="CREATE TABLE test.bloom_filter_idx ( u64 UInt64, i32 Int32, f64 Float64, d Decimal(10, 2), s String, e Enum8('a' = 1, 'b' = 2, 'c' = 3), dt Date, INDEX bloom_filter_a i32 TYPE bloom_filter($rate) GRANULARITY 1 ) ENGINE = MergeTree() ORDER BY u64 SETTINGS index_granularity = 8192" +done diff --git a/dbms/tests/queries/0_stateless/00945_bloom_filter_index.reference b/dbms/tests/queries/0_stateless/00945_bloom_filter_index.reference new file mode 100755 index 00000000000..7b6d919d404 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00945_bloom_filter_index.reference @@ -0,0 +1,30 @@ +1 +0 +1 +1 +2 +0 +2 +2 +2 +0 +2 +2 +2 +0 +2 +2 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 diff --git a/dbms/tests/queries/0_stateless/00945_bloom_filter_index.sql b/dbms/tests/queries/0_stateless/00945_bloom_filter_index.sql new file mode 100755 index 00000000000..bb258b886a4 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00945_bloom_filter_index.sql @@ -0,0 +1,50 @@ +SET allow_experimental_data_skipping_indices = 1; + +DROP TABLE IF EXISTS test.single_column_bloom_filter; + +CREATE TABLE test.single_column_bloom_filter (u64 UInt64, i32 Int32, i64 UInt64, INDEX idx (i32) TYPE bloom_filter GRANULARITY 1) ENGINE = MergeTree() ORDER BY u64 SETTINGS index_granularity = 6; + +INSERT INTO test.single_column_bloom_filter SELECT number AS u64, number AS i32, number AS i64 FROM system.numbers LIMIT 100; + +SELECT COUNT() FROM test.single_column_bloom_filter WHERE i32 = 1 SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i32, i32) = (1, 2) SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i32, i64) = (1, 1) SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i64, (i64, i32)) = (1, (1, 1)) SETTINGS max_rows_to_read = 6; + +SELECT COUNT() FROM test.single_column_bloom_filter WHERE i32 IN (1, 2) SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i32, i32) IN ((1, 2), (2, 3)) SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i32, i64) IN ((1, 1), (2, 2)) SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i64, (i64, i32)) IN ((1, (1, 1)), (2, (2, 2))) SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.single_column_bloom_filter WHERE i32 IN (SELECT arrayJoin([toInt32(1), toInt32(2)])) SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i32, i32) IN (SELECT arrayJoin([(toInt32(1), toInt32(2)), (toInt32(2), toInt32(3))])) SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i32, i64) IN (SELECT arrayJoin([(toInt32(1), toUInt64(1)), (toInt32(2), toUInt64(2))])) SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i64, (i64, i32)) IN (SELECT arrayJoin([(toUInt64(1), (toUInt64(1), toInt32(1))), (toUInt64(2), (toUInt64(2), toInt32(2)))])) SETTINGS max_rows_to_read = 6; +WITH (1, 2) AS liter_prepared_set SELECT COUNT() FROM test.single_column_bloom_filter WHERE i32 IN liter_prepared_set SETTINGS max_rows_to_read = 6; +WITH ((1, 2), (2, 3)) AS liter_prepared_set SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i32, i32) IN liter_prepared_set SETTINGS max_rows_to_read = 6; +WITH ((1, 1), (2, 2)) AS liter_prepared_set SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i32, i64) IN liter_prepared_set SETTINGS max_rows_to_read = 6; +WITH ((1, (1, 1)), (2, (2, 2))) AS liter_prepared_set SELECT COUNT() FROM test.single_column_bloom_filter WHERE (i64, (i64, i32)) IN liter_prepared_set SETTINGS max_rows_to_read = 6; + +DROP TABLE IF EXISTS test.single_column_bloom_filter; + + +DROP TABLE IF EXISTS test.bloom_filter_types_test; + +CREATE TABLE test.bloom_filter_types_test (order_key UInt64, i8 Int8, i16 Int16, i32 Int32, i64 Int64, u8 UInt8, u16 UInt16, u32 UInt32, u64 UInt64, f32 Float32, f64 Float64, date Date, date_time DateTime('Europe/Moscow'), str String, fixed_string FixedString(5), INDEX idx (i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, date, date_time, str, fixed_string) TYPE bloom_filter GRANULARITY 1) ENGINE = MergeTree() ORDER BY order_key SETTINGS index_granularity = 6; +INSERT INTO test.bloom_filter_types_test SELECT number AS order_key, toInt8(number) AS i8, toInt16(number) AS i16, toInt32(number) AS i32, toInt64(number) AS i64, toUInt8(number) AS u8, toUInt16(number) AS u16, toUInt32(number) AS u32, toUInt64(number) AS u64, toFloat32(number) AS f32, toFloat64(number) AS f64, toDate(number, 'Europe/Moscow') AS date, toDateTime(number, 'Europe/Moscow') AS date_time, toString(number) AS str, toFixedString(toString(number), 5) AS fixed_string FROM system.numbers LIMIT 100; + +SELECT COUNT() FROM test.bloom_filter_types_test WHERE i8 = 1 SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE i16 = 1 SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE i32 = 1 SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE i64 = 1 SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE u8 = 1 SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE u16 = 1 SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE u32 = 1 SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE u64 = 1 SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE f32 = 1 SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE f64 = 1 SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE date = '1970-01-02' SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE date_time = toDateTime('1970-01-01 03:00:01', 'Europe/Moscow') SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE str = '1' SETTINGS max_rows_to_read = 6; +SELECT COUNT() FROM test.bloom_filter_types_test WHERE fixed_string = toFixedString('1', 5) SETTINGS max_rows_to_read = 12; + +DROP TABLE IF EXISTS test.bloom_filter_types_test; diff --git a/dbms/tests/queries/0_stateless/00950_test_double_delta_codec.reference b/dbms/tests/queries/0_stateless/00950_test_double_delta_codec.reference index 5fb3bfb3629..eabb2f48147 100644 --- a/dbms/tests/queries/0_stateless/00950_test_double_delta_codec.reference +++ b/dbms/tests/queries/0_stateless/00950_test_double_delta_codec.reference @@ -8,3 +8,4 @@ I16 I8 DT D +Compression: diff --git a/dbms/tests/queries/0_stateless/00950_test_double_delta_codec.sql b/dbms/tests/queries/0_stateless/00950_test_double_delta_codec.sql index a5ae4766ece..93c6b0d749b 100644 --- a/dbms/tests/queries/0_stateless/00950_test_double_delta_codec.sql +++ b/dbms/tests/queries/0_stateless/00950_test_double_delta_codec.sql @@ -29,23 +29,23 @@ CREATE TABLE codecTest ( -- checking for overflow INSERT INTO codecTest (key, ref_valueU64, valueU64, ref_valueI64, valueI64) - VALUES (101, 18446744073709551615, 18446744073709551615, 9223372036854775807, 9223372036854775807), (202, 0, 0, -9223372036854775808, -9223372036854775808), (203, 18446744073709551615, 18446744073709551615, 9223372036854775807, 9223372036854775807); + VALUES (1, 18446744073709551615, 18446744073709551615, 9223372036854775807, 9223372036854775807), (2, 0, 0, -9223372036854775808, -9223372036854775808), (3, 18446744073709551615, 18446744073709551615, 9223372036854775807, 9223372036854775807); -- n^3 covers all double delta storage cases, from small difference between neighbouref_values (stride) to big. INSERT INTO codecTest (key, ref_valueU64, valueU64, ref_valueU32, valueU32, ref_valueU16, valueU16, ref_valueU8, valueU8, ref_valueI64, valueI64, ref_valueI32, valueI32, ref_valueI16, valueI16, ref_valueI8, valueI8, ref_valueDT, valueDT, ref_valueD, valueD) SELECT number as n, n * n * n as v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, toDateTime(v), toDateTime(v), toDate(v), toDate(v) - FROM system.numbers LIMIT 101, 100; + FROM system.numbers LIMIT 101, 1000; -- best case - constant stride INSERT INTO codecTest (key, ref_valueU64, valueU64, ref_valueU32, valueU32, ref_valueU16, valueU16, ref_valueU8, valueU8, ref_valueI64, valueI64, ref_valueI32, valueI32, ref_valueI16, valueI16, ref_valueI8, valueI8, ref_valueDT, valueDT, ref_valueD, valueD) SELECT number as n, n as v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, toDateTime(v), toDateTime(v), toDate(v), toDate(v) - FROM system.numbers LIMIT 201, 100; + FROM system.numbers LIMIT 2001, 1000; -- worst case - random stride INSERT INTO codecTest (key, ref_valueU64, valueU64, ref_valueU32, valueU32, ref_valueU16, valueU16, ref_valueU8, valueU8, ref_valueI64, valueI64, ref_valueI32, valueI32, ref_valueI16, valueI16, ref_valueI8, valueI8, ref_valueDT, valueDT, ref_valueD, valueD) SELECT number as n, n + (rand64() - 9223372036854775807)/1000 as v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, v, toDateTime(v), toDateTime(v), toDate(v), toDate(v) - FROM system.numbers LIMIT 301, 100; + FROM system.numbers LIMIT 3001, 1000; SELECT 'U64'; @@ -147,5 +147,21 @@ WHERE dD != 0 LIMIT 10; +SELECT 'Compression:'; +SELECT + table, name, type, + compression_codec, + data_uncompressed_bytes u, + data_compressed_bytes c, + round(u/c,3) ratio +FROM system.columns +WHERE + table == 'codecTest' +AND + compression_codec != '' +AND + ratio <= 1 +ORDER BY + table, name, type; DROP TABLE IF EXISTS codecTest; \ No newline at end of file diff --git a/dbms/tests/queries/0_stateless/00951_ngram_entry.reference b/dbms/tests/queries/0_stateless/00951_ngram_search.reference similarity index 68% rename from dbms/tests/queries/0_stateless/00951_ngram_entry.reference rename to dbms/tests/queries/0_stateless/00951_ngram_search.reference index d6d97eaaab9..1b845b6015d 100644 --- a/dbms/tests/queries/0_stateless/00951_ngram_entry.reference +++ b/dbms/tests/queries/0_stateless/00951_ngram_search.reference @@ -1,13 +1,8 @@ -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 +1000 +1000 +1000 +1000 +1000 1000 1000 1000 @@ -18,98 +13,202 @@ 0 0 0 -0 -0 -0 -0 -0 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 500 500 500 500 500 -1000 -1000 -1000 -1000 -1000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1000 1000 0 -0 +1000 +1000 500 -1000 +0 +привет как дела?... Херсон 1000 +привет как дела клип - Яндекс.Видео 1000 +привет 1000 +пап привет как дела - Яндекс.Видео 1000 +привет братан как дела - Яндекс.Видео 1000 +http://metric.ru/ 1000 +http://autometric.ru/ 1000 +http://metrica.yandex.com/ 1000 +http://metris.ru/ 1000 +http://metrika.ru/ 1000 + 1000 +привет как дела?... Херсон 1000 +привет как дела клип - Яндекс.Видео 1000 +привет 1000 +пап привет как дела - Яндекс.Видео 1000 +привет братан как дела - Яндекс.Видео 1000 +http://metric.ru/ 1000 +http://autometric.ru/ 1000 +http://metrica.yandex.com/ 1000 +http://metris.ru/ 1000 +http://metrika.ru/ 1000 + 1000 +привет как дела?... Херсон 1000 +привет как дела клип - Яндекс.Видео 1000 +привет 1000 +пап привет как дела - Яндекс.Видео 1000 +привет братан как дела - Яндекс.Видео 1000 +http://metric.ru/ 1000 +http://autometric.ru/ 1000 +http://metrica.yandex.com/ 1000 +http://metris.ru/ 1000 +http://metrika.ru/ 1000 + 1000 +http://metric.ru/ 0 +http://autometric.ru/ 0 +http://metrica.yandex.com/ 0 +http://metris.ru/ 0 +http://metrika.ru/ 0 + 0 +привет 308 +привет братан как дела - Яндекс.Видео 923 +привет как дела?... Херсон 1000 +привет как дела клип - Яндекс.Видео 1000 +пап привет как дела - Яндекс.Видео 1000 +http://metric.ru/ 0 +http://autometric.ru/ 0 +http://metrica.yandex.com/ 0 +http://metris.ru/ 0 +http://metrika.ru/ 0 + 0 +привет 308 +привет как дела?... Херсон 769 +привет как дела клип - Яндекс.Видео 769 +привет братан как дела - Яндекс.Видео 769 +пап привет как дела - Яндекс.Видео 846 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metric.ru/ 600 +http://autometric.ru/ 600 +http://metrica.yandex.com/ 600 +http://metris.ru/ 600 +http://metrika.ru/ 1000 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metris.ru/ 600 +http://metrika.ru/ 600 +http://metric.ru/ 800 +http://autometric.ru/ 800 +http://metrica.yandex.com/ 1000 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metric.ru/ 600 +http://autometric.ru/ 600 +http://metrica.yandex.com/ 600 +http://metris.ru/ 600 +http://metrika.ru/ 800 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metris.ru/ 600 +http://metrika.ru/ 600 +http://metric.ru/ 800 +http://autometric.ru/ 800 +http://metrica.yandex.com/ 800 привет как дела?... Херсон 0 привет как дела клип - Яндекс.Видео 0 привет 0 @@ -117,10 +216,232 @@ привет братан как дела - Яндекс.Видео 0 http://metric.ru/ 0 http://autometric.ru/ 0 +http://metris.ru/ 0 +http://metrika.ru/ 0 + 0 +http://metrica.yandex.com/ 1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +0 +0 +0 +0 +0 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +500 +500 +500 +500 +500 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1000 +1000 +0 +571 +1000 +500 +0 +привет как дела?... Херсон 1000 +привет как дела клип - Яндекс.Видео 1000 +привет 1000 +пап привет как дела - Яндекс.Видео 1000 +привет братан как дела - Яндекс.Видео 1000 +http://metric.ru/ 1000 +http://autometric.ru/ 1000 +http://metrica.yandex.com/ 1000 +http://metris.ru/ 1000 +http://metrika.ru/ 1000 + 1000 +привет как дела?... Херсон 1000 +привет как дела клип - Яндекс.Видео 1000 +привет 1000 +пап привет как дела - Яндекс.Видео 1000 +привет братан как дела - Яндекс.Видео 1000 +http://metric.ru/ 1000 +http://autometric.ru/ 1000 +http://metrica.yandex.com/ 1000 +http://metris.ru/ 1000 +http://metrika.ru/ 1000 + 1000 +привет как дела?... Херсон 1000 +привет как дела клип - Яндекс.Видео 1000 +привет 1000 +пап привет как дела - Яндекс.Видео 1000 +привет братан как дела - Яндекс.Видео 1000 +http://metric.ru/ 1000 +http://autometric.ru/ 1000 +http://metrica.yandex.com/ 1000 +http://metris.ru/ 1000 +http://metrika.ru/ 1000 + 1000 +http://metric.ru/ 0 +http://autometric.ru/ 0 http://metrica.yandex.com/ 0 http://metris.ru/ 0 http://metrika.ru/ 0 0 +привет 308 +привет братан как дела - Яндекс.Видео 923 +привет как дела?... Херсон 1000 +привет как дела клип - Яндекс.Видео 1000 +пап привет как дела - Яндекс.Видео 1000 +http://metric.ru/ 0 +http://autometric.ru/ 0 +http://metrica.yandex.com/ 0 +http://metris.ru/ 0 +http://metrika.ru/ 0 + 0 +привет 308 +привет как дела?... Херсон 769 +привет как дела клип - Яндекс.Видео 769 +привет братан как дела - Яндекс.Видео 769 +пап привет как дела - Яндекс.Видео 846 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metric.ru/ 600 +http://autometric.ru/ 600 +http://metrica.yandex.com/ 600 +http://metris.ru/ 600 +http://metrika.ru/ 1000 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metric.ru/ 600 +http://autometric.ru/ 600 +http://metrica.yandex.com/ 600 +http://metris.ru/ 600 +http://metrika.ru/ 1000 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metris.ru/ 600 +http://metrika.ru/ 600 +http://metric.ru/ 800 +http://autometric.ru/ 800 +http://metrica.yandex.com/ 1000 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metric.ru/ 600 +http://autometric.ru/ 600 +http://metrica.yandex.com/ 600 +http://metris.ru/ 600 +http://metrika.ru/ 800 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metris.ru/ 600 +http://metrika.ru/ 600 +http://metric.ru/ 800 +http://autometric.ru/ 800 +http://metrica.yandex.com/ 800 привет как дела?... Херсон 0 привет как дела клип - Яндекс.Видео 0 привет 0 @@ -128,108 +449,46 @@ http://metrika.ru/ 0 привет братан как дела - Яндекс.Видео 0 http://metric.ru/ 0 http://autometric.ru/ 0 -http://metrica.yandex.com/ 0 http://metris.ru/ 0 http://metrika.ru/ 0 0 -привет как дела?... Херсон 0 -привет как дела клип - Яндекс.Видео 0 -привет 0 -пап привет как дела - Яндекс.Видео 0 -привет братан как дела - Яндекс.Видео 0 +http://metrica.yandex.com/ 1000 http://metric.ru/ 0 http://autometric.ru/ 0 http://metrica.yandex.com/ 0 http://metris.ru/ 0 http://metrika.ru/ 0 0 -привет как дела?... Херсон 0 -привет как дела клип - Яндекс.Видео 0 -пап привет как дела - Яндекс.Видео 0 -привет братан как дела - Яндекс.Видео 77 -привет 692 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metrica.yandex.com/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -пап привет как дела - Яндекс.Видео 154 -привет как дела?... Херсон 231 -привет как дела клип - Яндекс.Видео 231 -привет братан как дела - Яндекс.Видео 231 -привет 692 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metrica.yandex.com/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -http://metrika.ru/ 0 -http://metric.ru/ 400 -http://autometric.ru/ 400 -http://metrica.yandex.com/ 400 -http://metris.ru/ 400 -привет как дела?... Херсон 1000 +привет 121 +привет как дела?... Херсон 394 +привет братан как дела - Яндекс.Видео 788 +пап привет как дела - Яндекс.Видео 818 привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrica.yandex.com/ 0 -http://metric.ru/ 200 -http://autometric.ru/ 200 -http://metris.ru/ 400 -http://metrika.ru/ 400 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrika.ru/ 200 -http://metric.ru/ 400 -http://autometric.ru/ 400 -http://metrica.yandex.com/ 400 -http://metris.ru/ 400 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metric.ru/ 200 -http://autometric.ru/ 200 -http://metrica.yandex.com/ 200 -http://metris.ru/ 400 -http://metrika.ru/ 400 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrica.yandex.com/ 0 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 1000 1000 1000 @@ -240,616 +499,357 @@ http://metrika.ru/ 1000 0 0 0 -0 -0 -0 -0 -0 -500 -500 -500 -500 -500 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 1000 1000 1000 1000 1000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0 -0 1000 -429 -0 -500 1000 -привет как дела?... Херсон 0 -привет как дела клип - Яндекс.Видео 0 -привет 0 -пап привет как дела - Яндекс.Видео 0 -привет братан как дела - Яндекс.Видео 0 http://metric.ru/ 0 http://autometric.ru/ 0 http://metrica.yandex.com/ 0 http://metris.ru/ 0 http://metrika.ru/ 0 0 -привет как дела?... Херсон 0 -привет как дела клип - Яндекс.Видео 0 -привет 0 -пап привет как дела - Яндекс.Видео 0 -привет братан как дела - Яндекс.Видео 0 +привет 360 +привет братан как дела - Яндекс.Видео 960 +привет как дела?... Херсон 1000 +привет как дела клип - Яндекс.Видео 1000 +пап привет как дела - Яндекс.Видео 1000 http://metric.ru/ 0 http://autometric.ru/ 0 http://metrica.yandex.com/ 0 http://metris.ru/ 0 http://metrika.ru/ 0 0 -привет как дела?... Херсон 0 -привет как дела клип - Яндекс.Видео 0 -привет 0 -пап привет как дела - Яндекс.Видео 0 -привет братан как дела - Яндекс.Видео 0 -http://metric.ru/ 0 -http://autometric.ru/ 0 -http://metrica.yandex.com/ 0 -http://metris.ru/ 0 -http://metrika.ru/ 0 - 0 -привет как дела?... Херсон 0 -привет как дела клип - Яндекс.Видео 0 -пап привет как дела - Яндекс.Видео 0 -привет братан как дела - Яндекс.Видео 77 -привет 692 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metrica.yandex.com/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -пап привет как дела - Яндекс.Видео 154 -привет как дела?... Херсон 231 -привет как дела клип - Яндекс.Видео 231 -привет братан как дела - Яндекс.Видео 231 -привет 692 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metrica.yandex.com/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -http://metrika.ru/ 0 -http://metric.ru/ 400 -http://autometric.ru/ 400 -http://metrica.yandex.com/ 400 -http://metris.ru/ 400 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrika.ru/ 0 -http://metric.ru/ 400 -http://autometric.ru/ 400 -http://metrica.yandex.com/ 400 -http://metris.ru/ 400 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrica.yandex.com/ 0 -http://metric.ru/ 200 -http://autometric.ru/ 200 -http://metris.ru/ 400 -http://metrika.ru/ 400 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrika.ru/ 200 -http://metric.ru/ 400 -http://autometric.ru/ 400 -http://metrica.yandex.com/ 400 -http://metris.ru/ 400 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metric.ru/ 200 -http://autometric.ru/ 200 -http://metrica.yandex.com/ 200 -http://metris.ru/ 400 -http://metrika.ru/ 400 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrica.yandex.com/ 0 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -привет как дела клип - Яндекс.Видео 0 -пап привет как дела - Яндекс.Видео 182 -привет братан как дела - Яндекс.Видео 212 -привет как дела?... Херсон 606 -привет 879 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metrica.yandex.com/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -1000 -1000 -1000 -1000 -1000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0 -0 -0 -0 -0 -0 -0 -привет как дела?... Херсон 0 -привет как дела клип - Яндекс.Видео 0 -пап привет как дела - Яндекс.Видео 0 -привет братан как дела - Яндекс.Видео 40 -привет 640 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metrica.yandex.com/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -пап привет как дела - Яндекс.Видео 80 -привет как дела?... Херсон 120 -привет как дела клип - Яндекс.Видео 120 -привет братан как дела - Яндекс.Видео 120 -привет 640 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metrica.yandex.com/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -http://metrika.ru/ 0 -http://metric.ru/ 500 -http://autometric.ru/ 500 -http://metrica.yandex.com/ 500 -http://metris.ru/ 500 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrica.yandex.com/ 0 -http://metric.ru/ 250 -http://autometric.ru/ 250 -http://metris.ru/ 500 -http://metrika.ru/ 500 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrika.ru/ 250 -http://metric.ru/ 500 -http://autometric.ru/ 500 -http://metrica.yandex.com/ 500 -http://metris.ru/ 500 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metric.ru/ 250 -http://autometric.ru/ 250 -http://metrica.yandex.com/ 250 -http://metris.ru/ 500 -http://metrika.ru/ 500 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrica.yandex.com/ 0 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -1000 -1000 -1000 -1000 -1000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -0 -0 -0 -0 -0 -0 -0 +привет 360 привет как дела?... Херсон 880 привет как дела клип - Яндекс.Видео 880 -пап привет как дела - Яндекс.Видео 880 -привет братан как дела - Яндекс.Видео 920 -привет 1000 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metrica.yandex.com/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -привет как дела?... Херсон 560 -привет как дела клип - Яндекс.Видео 560 -пап привет как дела - Яндекс.Видео 560 -привет братан как дела - Яндекс.Видео 560 -привет 1000 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metrica.yandex.com/ 1000 -http://metris.ru/ 1000 -http://metrika.ru/ 1000 - 1000 -http://metrika.ru/ 0 +привет братан как дела - Яндекс.Видео 880 +пап привет как дела - Яндекс.Видео 920 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 http://metric.ru/ 500 http://autometric.ru/ 500 http://metrica.yandex.com/ 500 http://metris.ru/ 500 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrika.ru/ 0 -http://metric.ru/ 500 -http://autometric.ru/ 500 -http://metrica.yandex.com/ 500 -http://metris.ru/ 500 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrica.yandex.com/ 0 -http://metric.ru/ 250 -http://autometric.ru/ 250 +http://metrika.ru/ 1000 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 http://metris.ru/ 500 http://metrika.ru/ 500 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metrika.ru/ 250 +http://metric.ru/ 750 +http://autometric.ru/ 750 +http://metrica.yandex.com/ 1000 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 http://metric.ru/ 500 http://autometric.ru/ 500 http://metrica.yandex.com/ 500 http://metris.ru/ 500 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 -http://metric.ru/ 250 -http://autometric.ru/ 250 -http://metrica.yandex.com/ 250 +http://metrika.ru/ 750 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 http://metris.ru/ 500 http://metrika.ru/ 500 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 - 1000 +http://metric.ru/ 750 +http://autometric.ru/ 750 +http://metrica.yandex.com/ 750 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 +http://metric.ru/ 0 +http://autometric.ru/ 0 +http://metris.ru/ 0 +http://metrika.ru/ 0 + 0 +http://metrica.yandex.com/ 1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1000 +1000 +1000 +1000 +1000 +1000 +1000 +привет 0 +http://metric.ru/ 0 +http://autometric.ru/ 0 http://metrica.yandex.com/ 0 -привет как дела?... Херсон 1000 -привет как дела клип - Яндекс.Видео 1000 -привет 1000 -пап привет как дела - Яндекс.Видео 1000 -привет братан как дела - Яндекс.Видео 1000 -http://metric.ru/ 1000 -http://autometric.ru/ 1000 -http://metris.ru/ 1000 +http://metris.ru/ 0 +http://metrika.ru/ 0 + 0 +привет братан как дела - Яндекс.Видео 80 +привет как дела?... Херсон 120 +привет как дела клип - Яндекс.Видео 120 +пап привет как дела - Яндекс.Видео 120 +привет 0 +http://metric.ru/ 0 +http://autometric.ru/ 0 +http://metrica.yandex.com/ 0 +http://metris.ru/ 0 +http://metrika.ru/ 0 + 0 +привет как дела?... Херсон 440 +привет как дела клип - Яндекс.Видео 440 +пап привет как дела - Яндекс.Видео 440 +привет братан как дела - Яндекс.Видео 440 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metric.ru/ 500 +http://autometric.ru/ 500 +http://metrica.yandex.com/ 500 +http://metris.ru/ 500 http://metrika.ru/ 1000 - 1000 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metric.ru/ 500 +http://autometric.ru/ 500 +http://metrica.yandex.com/ 500 +http://metris.ru/ 500 +http://metrika.ru/ 1000 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metris.ru/ 500 +http://metrika.ru/ 500 +http://metric.ru/ 750 +http://autometric.ru/ 750 +http://metrica.yandex.com/ 1000 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metric.ru/ 500 +http://autometric.ru/ 500 +http://metrica.yandex.com/ 500 +http://metris.ru/ 500 +http://metrika.ru/ 750 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 + 0 +http://metris.ru/ 500 +http://metrika.ru/ 500 +http://metric.ru/ 750 +http://autometric.ru/ 750 +http://metrica.yandex.com/ 750 +привет как дела?... Херсон 0 +привет как дела клип - Яндекс.Видео 0 +привет 0 +пап привет как дела - Яндекс.Видео 0 +привет братан как дела - Яндекс.Видео 0 +http://metric.ru/ 0 +http://autometric.ru/ 0 +http://metris.ru/ 0 +http://metrika.ru/ 0 + 0 +http://metrica.yandex.com/ 1000 diff --git a/dbms/tests/queries/0_stateless/00951_ngram_entry.sql b/dbms/tests/queries/0_stateless/00951_ngram_search.sql similarity index 100% rename from dbms/tests/queries/0_stateless/00951_ngram_entry.sql rename to dbms/tests/queries/0_stateless/00951_ngram_search.sql diff --git a/dbms/tests/queries/0_stateless/00954_client_prepared_statements.reference b/dbms/tests/queries/0_stateless/00954_client_prepared_statements.reference new file mode 100644 index 00000000000..f25c522a3c5 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00954_client_prepared_statements.reference @@ -0,0 +1,11 @@ +1 Hello, world 2005-05-05 05:05:05 +1 Hello, world 2005-05-05 05:05:05 +2 test 2005-05-25 15:00:00 +2 test 2005-05-25 15:00:00 +Code: 456. +abc +abc +Hello, world +Hello, world +0 +0 diff --git a/dbms/tests/queries/0_stateless/00954_client_prepared_statements.sh b/dbms/tests/queries/0_stateless/00954_client_prepared_statements.sh new file mode 100755 index 00000000000..c90dc92a7ef --- /dev/null +++ b/dbms/tests/queries/0_stateless/00954_client_prepared_statements.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +. $CURDIR/../shell_config.sh + +$CLICKHOUSE_CLIENT -q "DROP TABLE IF EXISTS ps"; +$CLICKHOUSE_CLIENT -q "CREATE TABLE ps (i UInt8, s String, d DateTime) ENGINE = Memory"; + +$CLICKHOUSE_CLIENT -q "INSERT INTO ps VALUES (1, 'Hello, world', '2005-05-05 05:05:05')"; +$CLICKHOUSE_CLIENT -q "INSERT INTO ps VALUES (2, 'test', '2005-05-25 15:00:00')"; + +$CLICKHOUSE_CLIENT --max_threads=1 --param_id=1 \ + -q "SELECT * FROM ps WHERE i = {id:UInt8}"; +$CLICKHOUSE_CLIENT --max_threads=1 --param_phrase='Hello, world' \ + -q "SELECT * FROM ps WHERE s = {phrase:String}"; +$CLICKHOUSE_CLIENT --max_threads=1 --param_date='2005-05-25 15:00:00' \ + -q "SELECT * FROM ps WHERE d = {date:DateTime}"; +$CLICKHOUSE_CLIENT --max_threads=1 --param_id=2 --param_phrase='test' \ + -q "SELECT * FROM ps WHERE i = {id:UInt8} and s = {phrase:String}"; + +$CLICKHOUSE_CLIENT -q "SELECT {s:String}" 2>&1 | grep -oP '^Code: 456\.' + +$CLICKHOUSE_CLIENT -q "DROP TABLE ps"; + + +$CLICKHOUSE_CLIENT --param_test abc --query 'SELECT {test:String}' +$CLICKHOUSE_CLIENT --param_test=abc --query 'SELECT {test:String}' + +$CLICKHOUSE_CLIENT --param_test 'Hello, world' --query 'SELECT {test:String}' +$CLICKHOUSE_CLIENT --param_test='Hello, world' --query 'SELECT {test:String}' + +$CLICKHOUSE_CLIENT --param_test '' --query 'SELECT length({test:String})' +$CLICKHOUSE_CLIENT --param_test='' --query 'SELECT length({test:String})' diff --git a/dbms/tests/queries/0_stateless/00955_complex_prepared_statements.reference b/dbms/tests/queries/0_stateless/00955_complex_prepared_statements.reference new file mode 100644 index 00000000000..701cc5f8781 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00955_complex_prepared_statements.reference @@ -0,0 +1,6 @@ +(1,'Hello') +(1,('dt',2)) +[10,10,10] +[[10],[10],[10]] +[10,10,10] [[10],[10],[10]] (10,'Test') (10,('dt',10)) 2015-02-15 +Code: 457. diff --git a/dbms/tests/queries/0_stateless/00955_complex_prepared_statements.sh b/dbms/tests/queries/0_stateless/00955_complex_prepared_statements.sh new file mode 100755 index 00000000000..fd30921b1ac --- /dev/null +++ b/dbms/tests/queries/0_stateless/00955_complex_prepared_statements.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +. $CURDIR/../shell_config.sh + +EXCEPTION_TEXT="Code: 457." + +$CLICKHOUSE_CLIENT -q "DROP TABLE IF EXISTS ps"; +$CLICKHOUSE_CLIENT -q "CREATE TABLE ps ( + a Array(UInt32), da Array(Array(UInt8)), + t Tuple(Int16, String), dt Tuple(UInt8, Tuple(String, UInt8)), + n Nullable(Date) + ) ENGINE = Memory"; + +$CLICKHOUSE_CLIENT -q "INSERT INTO ps VALUES ( + [1, 2], [[1, 1], [2, 2]], + (1, 'Hello'), (1, ('dt', 2)), + NULL)"; +$CLICKHOUSE_CLIENT -q "INSERT INTO ps VALUES ( + [10, 10, 10], [[10], [10], [10]], + (10, 'Test'), (10, ('dt', 10)), + '2015-02-15')"; + +$CLICKHOUSE_CLIENT --max_threads=1 --param_aui="[1, 2]" \ + -q "SELECT t FROM ps WHERE a = {aui:Array(UInt16)}"; +$CLICKHOUSE_CLIENT --max_threads=1 --param_d_a="[[1, 1], [2, 2]]" \ + -q "SELECT dt FROM ps WHERE da = {d_a:Array(Array(UInt8))}"; +$CLICKHOUSE_CLIENT --max_threads=1 --param_tisd="(10, 'Test')" \ + -q "SELECT a FROM ps WHERE t = {tisd:Tuple(Int16, String)}"; +$CLICKHOUSE_CLIENT --max_threads=1 --param_d_t="(10, ('dt', 10))" \ + -q "SELECT da FROM ps WHERE dt = {d_t:Tuple(UInt8, Tuple(String, UInt8))}"; +$CLICKHOUSE_CLIENT --max_threads=1 --param_nd="2015-02-15" \ + -q "SELECT * FROM ps WHERE n = {nd:Nullable(Date)}"; + +# Must throw an exception to avoid SQL injection +$CLICKHOUSE_CLIENT --max_threads=1 --param_injection="[1] OR 1" \ + -q "SELECT * FROM ps WHERE a = {injection:Array(UInt32)}" 2>&1 \ + | grep -o "$EXCEPTION_TEXT" + +$CLICKHOUSE_CLIENT -q "DROP TABLE ps"; diff --git a/dbms/tests/queries/0_stateless/00956_http_prepared_statements.reference b/dbms/tests/queries/0_stateless/00956_http_prepared_statements.reference new file mode 100644 index 00000000000..28323dae39b --- /dev/null +++ b/dbms/tests/queries/0_stateless/00956_http_prepared_statements.reference @@ -0,0 +1,4 @@ +1 Hello, world 2005-05-05 +1 Hello, world 2005-05-05 +2 test 2019-05-25 +2 test 2019-05-25 diff --git a/dbms/tests/queries/0_stateless/00956_http_prepared_statements.sh b/dbms/tests/queries/0_stateless/00956_http_prepared_statements.sh new file mode 100755 index 00000000000..e022ff65fc2 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00956_http_prepared_statements.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +. $CURDIR/../shell_config.sh + +${CLICKHOUSE_CURL} -sS $CLICKHOUSE_URL -d "DROP TABLE IF EXISTS ps"; +${CLICKHOUSE_CURL} -sS $CLICKHOUSE_URL -d "CREATE TABLE ps (i UInt8, s String, d Date) ENGINE = Memory"; + +${CLICKHOUSE_CURL} -sS $CLICKHOUSE_URL -d "INSERT INTO ps VALUES (1, 'Hello, world', '2005-05-05')"; +${CLICKHOUSE_CURL} -sS $CLICKHOUSE_URL -d "INSERT INTO ps VALUES (2, 'test', '2019-05-25')"; + +${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}?param_id=1" \ + -d "SELECT * FROM ps WHERE i = {id:UInt8} ORDER BY i, s, d"; +${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}?param_phrase=Hello,+world" \ + -d "SELECT * FROM ps WHERE s = {phrase:String} ORDER BY i, s, d"; +${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}?param_date=2019-05-25" \ + -d "SELECT * FROM ps WHERE d = {date:Date} ORDER BY i, s, d"; +${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}?param_id=2¶m_phrase=test" \ + -d "SELECT * FROM ps WHERE i = {id:UInt8} and s = {phrase:String} ORDER BY i, s, d"; + +${CLICKHOUSE_CURL} -sS $CLICKHOUSE_URL -d "DROP TABLE ps"; diff --git a/dbms/tests/queries/0_stateless/00957_coalesce_const_nullable_crash.reference b/dbms/tests/queries/0_stateless/00957_coalesce_const_nullable_crash.reference new file mode 100644 index 00000000000..61841cdb8f1 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00957_coalesce_const_nullable_crash.reference @@ -0,0 +1,11 @@ +1 Nullable(UInt8) +2 Nullable(UInt8) +1 Nullable(UInt8) +\N Nullable(Nothing) +1 Nullable(UInt8) +2 Nullable(UInt8) +1 Nullable(UInt8) +\N Nullable(Nothing) +1 LowCardinality(Nullable(UInt8)) +2 LowCardinality(Nullable(UInt8)) +1 LowCardinality(Nullable(UInt8)) diff --git a/dbms/tests/queries/0_stateless/00957_coalesce_const_nullable_crash.sql b/dbms/tests/queries/0_stateless/00957_coalesce_const_nullable_crash.sql new file mode 100644 index 00000000000..39e148c5751 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00957_coalesce_const_nullable_crash.sql @@ -0,0 +1,13 @@ +SELECT coalesce(toNullable(1), toNullable(2)) as x, toTypeName(x); +SELECT coalesce(NULL, toNullable(2)) as x, toTypeName(x); +SELECT coalesce(toNullable(1), NULL) as x, toTypeName(x); +SELECT coalesce(NULL, NULL) as x, toTypeName(x); + +SELECT coalesce(toNullable(materialize(1)), toNullable(materialize(2))) as x, toTypeName(x); +SELECT coalesce(NULL, toNullable(materialize(2))) as x, toTypeName(x); +SELECT coalesce(toNullable(materialize(1)), NULL) as x, toTypeName(x); +SELECT coalesce(materialize(NULL), materialize(NULL)) as x, toTypeName(x); + +SELECT coalesce(toLowCardinality(toNullable(1)), toLowCardinality(toNullable(2))) as x, toTypeName(x); +SELECT coalesce(NULL, toLowCardinality(toNullable(2))) as x, toTypeName(x); +SELECT coalesce(toLowCardinality(toNullable(1)), NULL) as x, toTypeName(x); diff --git a/dbms/tests/queries/0_stateless/00957_format_with_clashed_aliases.reference b/dbms/tests/queries/0_stateless/00957_format_with_clashed_aliases.reference new file mode 100644 index 00000000000..d3f7a9aa18b --- /dev/null +++ b/dbms/tests/queries/0_stateless/00957_format_with_clashed_aliases.reference @@ -0,0 +1,7 @@ +SELECT + 1 AS x, + x.y +FROM +( + SELECT 'Hello, world' AS y +) AS x diff --git a/dbms/tests/queries/0_stateless/00957_format_with_clashed_aliases.sh b/dbms/tests/queries/0_stateless/00957_format_with_clashed_aliases.sh new file mode 100755 index 00000000000..7268a1e1a93 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00957_format_with_clashed_aliases.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +. $CURDIR/../shell_config.sh + +set -e + +format="$CLICKHOUSE_FORMAT" + +echo "SELECT 1 AS x, x.y FROM (SELECT 'Hello, world' AS y) AS x" | $format diff --git a/dbms/tests/queries/0_stateless/00958_format_of_tuple_array_element.reference b/dbms/tests/queries/0_stateless/00958_format_of_tuple_array_element.reference new file mode 100644 index 00000000000..7265311960f --- /dev/null +++ b/dbms/tests/queries/0_stateless/00958_format_of_tuple_array_element.reference @@ -0,0 +1,9 @@ +SELECT + (x.1)[1], + (((x[1]).1)[1]).1, + (NOT x)[1], + -(x[1]), + (-x)[1], + (NOT x).1, + -(x.1), + (-x).1 diff --git a/dbms/tests/queries/0_stateless/00958_format_of_tuple_array_element.sh b/dbms/tests/queries/0_stateless/00958_format_of_tuple_array_element.sh new file mode 100755 index 00000000000..47f8e99bbb8 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00958_format_of_tuple_array_element.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +. $CURDIR/../shell_config.sh + +set -e + +format="$CLICKHOUSE_FORMAT" + +echo "SELECT (x.1)[1], (x[1].1)[1].1, (NOT x)[1], -x[1], (-x)[1], (NOT x).1, -x.1, (-x).1" | $format diff --git a/dbms/tests/queries/0_stateless/00959_format_with_different_aliases.reference b/dbms/tests/queries/0_stateless/00959_format_with_different_aliases.reference new file mode 100644 index 00000000000..8feb70c2fc4 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00959_format_with_different_aliases.reference @@ -0,0 +1,3 @@ +SELECT a + b AS x, x +SELECT a + b AS x, a + c AS x +SELECT a + b AS x, x diff --git a/dbms/tests/queries/0_stateless/00959_format_with_different_aliases.sh b/dbms/tests/queries/0_stateless/00959_format_with_different_aliases.sh new file mode 100755 index 00000000000..cad1083ad60 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00959_format_with_different_aliases.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +. $CURDIR/../shell_config.sh + +set -e + +format="$CLICKHOUSE_FORMAT --oneline" + +echo "SELECT a + b AS x, a + b AS x" | $format +echo "SELECT a + b AS x, a + c AS x" | $format +echo "SELECT a + b AS x, x" | $format diff --git a/dbms/tests/queries/0_stateless/00960_eval_ml_method_const.reference b/dbms/tests/queries/0_stateless/00960_eval_ml_method_const.reference new file mode 100644 index 00000000000..573541ac970 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00960_eval_ml_method_const.reference @@ -0,0 +1 @@ +0 diff --git a/dbms/tests/queries/0_stateless/00960_eval_ml_method_const.sql b/dbms/tests/queries/0_stateless/00960_eval_ml_method_const.sql new file mode 100644 index 00000000000..401c83af917 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00960_eval_ml_method_const.sql @@ -0,0 +1 @@ +WITH (SELECT stochasticLinearRegressionState(1, 2, 3)) AS model SELECT evalMLMethod(model, toFloat64(1), toFloat64(1)); diff --git a/dbms/tests/queries/0_stateless/00961_check_table.reference b/dbms/tests/queries/0_stateless/00961_check_table.reference new file mode 100644 index 00000000000..d85c66db622 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00961_check_table.reference @@ -0,0 +1,11 @@ +201901_1_1_0 1 +======== +201901_1_1_0 1 +201901_2_2_0 1 +======== +201901_1_2_1 1 +======== +201901_1_2_1 1 +201902_3_3_0 1 +======== +201902_3_4_1 1 diff --git a/dbms/tests/queries/0_stateless/00961_check_table.sql b/dbms/tests/queries/0_stateless/00961_check_table.sql new file mode 100644 index 00000000000..9752ffc3974 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00961_check_table.sql @@ -0,0 +1,37 @@ +DROP TABLE IF EXISTS mt_table; + +CREATE TABLE mt_table (d Date, key UInt64, data String) ENGINE = MergeTree() PARTITION BY toYYYYMM(d) ORDER BY key; + +CHECK TABLE mt_table; + +INSERT INTO mt_table VALUES (toDate('2019-01-02'), 1, 'Hello'), (toDate('2019-01-02'), 2, 'World'); + +CHECK TABLE mt_table; + +INSERT INTO mt_table VALUES (toDate('2019-01-02'), 3, 'quick'), (toDate('2019-01-02'), 4, 'brown'); + +SELECT '========'; + +CHECK TABLE mt_table; + +OPTIMIZE TABLE mt_table FINAL; + +SELECT '========'; + +CHECK TABLE mt_table; + +SELECT '========'; + +INSERT INTO mt_table VALUES (toDate('2019-02-03'), 5, '!'), (toDate('2019-02-03'), 6, '?'); + +CHECK TABLE mt_table; + +SELECT '========'; + +INSERT INTO mt_table VALUES (toDate('2019-02-03'), 7, 'jump'), (toDate('2019-02-03'), 8, 'around'); + +OPTIMIZE TABLE mt_table FINAL; + +CHECK TABLE mt_table PARTITION 201902; + +DROP TABLE IF EXISTS mt_table; diff --git a/dbms/tests/queries/0_stateless/00961_checksums_in_system_parts_columns_table.reference b/dbms/tests/queries/0_stateless/00961_checksums_in_system_parts_columns_table.reference new file mode 100644 index 00000000000..282b0ddca7b --- /dev/null +++ b/dbms/tests/queries/0_stateless/00961_checksums_in_system_parts_columns_table.reference @@ -0,0 +1 @@ +20000101_20000101_1_1_0 test_00961 1c63ae7a38eb76e2a71c28aaf0b3ae4d 0053df9b467cc5483e752ec62e91cfd4 da96ff1e527a8a1f908ddf2b1d0af239 diff --git a/dbms/tests/queries/0_stateless/00961_checksums_in_system_parts_columns_table.sql b/dbms/tests/queries/0_stateless/00961_checksums_in_system_parts_columns_table.sql new file mode 100644 index 00000000000..5f7774ac799 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00961_checksums_in_system_parts_columns_table.sql @@ -0,0 +1,17 @@ +DROP TABLE IF EXISTS test_00961; + +CREATE TABLE test_00961 (d Date, a String, b UInt8, x String, y Int8, z UInt32) ENGINE = MergeTree(d, (a, b), 111); + +INSERT INTO test_00961 VALUES ('2000-01-01', 'Hello, world!', 123, 'xxx yyy', -123, 123456789); + +SELECT + name, + table, + hash_of_all_files, + hash_of_uncompressed_files, + uncompressed_hash_of_compressed_files +FROM system.parts +WHERE table = 'test_00961'; + +DROP TABLE test_00961; + diff --git a/dbms/tests/queries/0_stateless/00961_visit_param_buffer_underflow.reference b/dbms/tests/queries/0_stateless/00961_visit_param_buffer_underflow.reference new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00961_visit_param_buffer_underflow.reference @@ -0,0 +1 @@ + diff --git a/dbms/tests/queries/0_stateless/00961_visit_param_buffer_underflow.sql b/dbms/tests/queries/0_stateless/00961_visit_param_buffer_underflow.sql new file mode 100644 index 00000000000..92b7501d700 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00961_visit_param_buffer_underflow.sql @@ -0,0 +1 @@ +SELECT visitParamExtractRaw('\"a\":', 'a'); diff --git a/dbms/tests/queries/0_stateless/00962_enumNotExect.reference b/dbms/tests/queries/0_stateless/00962_enumNotExect.reference new file mode 100644 index 00000000000..06e02da1be8 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00962_enumNotExect.reference @@ -0,0 +1,14 @@ +hello +world +hello +1 +2 +1 +hello +world +hello +1 +128 +1 +Enum16(\'a\' = 2, \'b\' = 128) +Enum8(\'a\' = 2, \'b\' = 127) diff --git a/dbms/tests/queries/0_stateless/00962_enumNotExect.sql b/dbms/tests/queries/0_stateless/00962_enumNotExect.sql new file mode 100644 index 00000000000..3431f238ad5 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00962_enumNotExect.sql @@ -0,0 +1,14 @@ +DROP TABLE IF EXISTS t_enum8; +CREATE TABLE t_enum8( x Enum('hello' = 1, 'world' = 2) ) ENGINE = TinyLog; +INSERT INTO t_enum8 Values('hello'),('world'),('hello'); +SELECT * FROM t_enum8; +SELECT CAST(x, 'Int8') FROM t_enum8; +DROP TABLE t_enum8; +DROP TABLE IF EXISTS t_enum16; +CREATE TABLE t_enum16( x Enum('hello' = 1, 'world' = 128) ) ENGINE = TinyLog; +INSERT INTO t_enum16 Values('hello'),('world'),('hello'); +SELECT * FROM t_enum16; +SELECT CAST(x, 'Int16') FROM t_enum16; +DROP TABLE t_enum16; +SELECT toTypeName(CAST('a', 'Enum(\'a\' = 2, \'b\' = 128)')); +SELECT toTypeName(CAST('a', 'Enum(\'a\' = 2, \'b\' = 127)')); diff --git a/dbms/tests/queries/0_stateless/00962_visit_param_various.reference b/dbms/tests/queries/0_stateless/00962_visit_param_various.reference new file mode 100644 index 00000000000..e1b066a6135 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00962_visit_param_various.reference @@ -0,0 +1,4 @@ +123 +Hello +Hello +0 diff --git a/dbms/tests/queries/0_stateless/00962_visit_param_various.sql b/dbms/tests/queries/0_stateless/00962_visit_param_various.sql new file mode 100644 index 00000000000..d65cb88c392 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00962_visit_param_various.sql @@ -0,0 +1,5 @@ +SELECT visitParamExtractUInt('"a":123', 'a'); +SELECT visitParamExtractString('"a":"Hello"', 'a'); +SELECT visitParamExtractRaw('"a":Hello}', 'a'); + +SELECT sum(ignore(visitParamExtractRaw(concat('{"a":', reinterpretAsString(rand64())), 'a'))) FROM numbers(1000000); diff --git a/dbms/tests/queries/0_stateless/00963_achimbab.reference b/dbms/tests/queries/0_stateless/00963_achimbab.reference new file mode 100644 index 00000000000..5248223efdd --- /dev/null +++ b/dbms/tests/queries/0_stateless/00963_achimbab.reference @@ -0,0 +1,57 @@ +{ + "meta": + [ + { + "name": "total", + "type": "Nullable(UInt8)" + }, + { + "name": "arrayElement(k, 1)", + "type": "Nullable(UInt16)" + }, + { + "name": "arrayElement(k, 2)", + "type": "Nullable(UInt16)" + } + ], + + "data": + [ + { + "total": 1, + "arrayElement(k, 1)": null, + "arrayElement(k, 2)": 4 + }, + { + "total": 1, + "arrayElement(k, 1)": null, + "arrayElement(k, 2)": 2 + }, + { + "total": 1, + "arrayElement(k, 1)": null, + "arrayElement(k, 2)": 1 + }, + { + "total": 1, + "arrayElement(k, 1)": null, + "arrayElement(k, 2)": 3 + }, + { + "total": 1, + "arrayElement(k, 1)": null, + "arrayElement(k, 2)": 5 + } + ], + + "totals": + { + "total": 1, + "arrayElement(k, 1)": null, + "arrayElement(k, 2)": null + }, + + "rows": 5, + + "rows_before_limit_at_least": 5 +} diff --git a/dbms/tests/queries/0_stateless/00963_achimbab.sql b/dbms/tests/queries/0_stateless/00963_achimbab.sql new file mode 100644 index 00000000000..d9d27429d39 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00963_achimbab.sql @@ -0,0 +1,18 @@ +SET output_format_write_statistics = 0; + +select + sum(cnt) > 0 as total, + k[1], k[2] + from + ( + select + arrayMap( x -> x % 3 ? toNullable(number%5 + x) : null, range(3)) as k, + number % 4 ? toNullable( rand() ) : Null as cnt + from system.numbers_mt + where number < 1000000 + limit 1000000 + ) +group by k with totals +order by total desc +SETTINGS max_threads = 100, max_execution_time = 120 +format JSON; diff --git a/dbms/tests/queries/0_stateless/00963_startsWith_force_primary_key.reference b/dbms/tests/queries/0_stateless/00963_startsWith_force_primary_key.reference new file mode 100644 index 00000000000..f1e5eeed2d9 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00963_startsWith_force_primary_key.reference @@ -0,0 +1,2 @@ +3 +2 diff --git a/dbms/tests/queries/0_stateless/00963_startsWith_force_primary_key.sql b/dbms/tests/queries/0_stateless/00963_startsWith_force_primary_key.sql new file mode 100644 index 00000000000..b3895a93b64 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00963_startsWith_force_primary_key.sql @@ -0,0 +1,6 @@ +DROP TABLE IF EXISTS test_startsWith; +CREATE TABLE test_startsWith (a String) Engine = MergeTree PARTITION BY tuple() ORDER BY a; +INSERT INTO test_startsWith (a) values ('a'), ('abcd'), ('bbb'), (''), ('abc'); +SELECT count() from test_startsWith where startsWith(a, 'a') settings force_primary_key=1; +SELECT count() from test_startsWith where startsWith(a, 'abc') settings force_primary_key=1; +DROP TABLE test_startsWith; diff --git a/dbms/tests/queries/0_stateless/00964_os_thread_priority.reference b/dbms/tests/queries/0_stateless/00964_os_thread_priority.reference new file mode 100644 index 00000000000..83b33d238da --- /dev/null +++ b/dbms/tests/queries/0_stateless/00964_os_thread_priority.reference @@ -0,0 +1 @@ +1000 diff --git a/dbms/tests/queries/0_stateless/00964_os_thread_priority.sql b/dbms/tests/queries/0_stateless/00964_os_thread_priority.sql new file mode 100644 index 00000000000..4244de8e909 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00964_os_thread_priority.sql @@ -0,0 +1,3 @@ +-- the setting exists and server does not crash +SET os_thread_priority = 10; +SELECT count() FROM numbers(1000); diff --git a/dbms/tests/queries/0_stateless/00965_shard_unresolvable_addresses.reference b/dbms/tests/queries/0_stateless/00965_shard_unresolvable_addresses.reference new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00965_shard_unresolvable_addresses.reference @@ -0,0 +1 @@ +1 diff --git a/dbms/tests/queries/0_stateless/00965_shard_unresolvable_addresses.sql b/dbms/tests/queries/0_stateless/00965_shard_unresolvable_addresses.sql new file mode 100644 index 00000000000..b6b981c7d00 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00965_shard_unresolvable_addresses.sql @@ -0,0 +1,2 @@ +SELECT count() FROM remote('127.0.0.1,localhos', system.one); -- { serverError 279 } +SELECT count() FROM remote('127.0.0.1|localhos', system.one); diff --git a/dbms/tests/queries/0_stateless/00966_invalid_json_must_not_parse.reference b/dbms/tests/queries/0_stateless/00966_invalid_json_must_not_parse.reference new file mode 100644 index 00000000000..f7eb44d66e0 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00966_invalid_json_must_not_parse.reference @@ -0,0 +1,6 @@ +0 +0 +0 +0 +0 +0 diff --git a/dbms/tests/queries/0_stateless/00966_invalid_json_must_not_parse.sql b/dbms/tests/queries/0_stateless/00966_invalid_json_must_not_parse.sql new file mode 100644 index 00000000000..afcbc78cfd5 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00966_invalid_json_must_not_parse.sql @@ -0,0 +1,12 @@ +SET allow_simdjson=1; + +SELECT JSONLength('"HX-='); +SELECT JSONLength('[9]\0\x42\xD3\x36\xE3'); +SELECT JSONLength(unhex('5B30000E06D7AA5D')); + + +SET allow_simdjson=0; + +SELECT JSONLength('"HX-='); +SELECT JSONLength('[9]\0\x42\xD3\x36\xE3'); +SELECT JSONLength(unhex('5B30000E06D7AA5D')); diff --git a/dbms/tests/queries/0_stateless/00967_ubsan_bit_test.reference b/dbms/tests/queries/0_stateless/00967_ubsan_bit_test.reference new file mode 100644 index 00000000000..573541ac970 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00967_ubsan_bit_test.reference @@ -0,0 +1 @@ +0 diff --git a/dbms/tests/queries/0_stateless/00967_ubsan_bit_test.sql b/dbms/tests/queries/0_stateless/00967_ubsan_bit_test.sql new file mode 100644 index 00000000000..1682e725670 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00967_ubsan_bit_test.sql @@ -0,0 +1 @@ +SELECT sum(ignore(bitTest(number, 65))) FROM numbers(10); diff --git a/dbms/tests/queries/0_stateless/00968_file_engine_in_subquery.reference b/dbms/tests/queries/0_stateless/00968_file_engine_in_subquery.reference new file mode 100644 index 00000000000..8b1acc12b63 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00968_file_engine_in_subquery.reference @@ -0,0 +1,10 @@ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 diff --git a/dbms/tests/queries/0_stateless/00968_file_engine_in_subquery.sql b/dbms/tests/queries/0_stateless/00968_file_engine_in_subquery.sql new file mode 100644 index 00000000000..5ed3be77cd6 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00968_file_engine_in_subquery.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS tableFile_00968; +DROP TABLE IF EXISTS tableMergeTree_00968; +CREATE TABLE tableFile_00968(number UInt64) ENGINE = File('TSV'); +CREATE TABLE tableMergeTree_00968(id UInt64) ENGINE = MergeTree() PARTITION BY id ORDER BY id; + +INSERT INTO tableFile_00968 SELECT number FROM system.numbers LIMIT 10; +INSERT INTO tableMergeTree_00968 SELECT number FROM system.numbers LIMIT 100; + +SELECT id FROM tableMergeTree_00968 WHERE id IN (SELECT number FROM tableFile_00968) ORDER BY id; diff --git a/dbms/tests/queries/0_stateless/00968_roundAge.reference b/dbms/tests/queries/0_stateless/00968_roundAge.reference new file mode 100644 index 00000000000..e85c792b528 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00968_roundAge.reference @@ -0,0 +1,7 @@ +0 +18 +25 +35 +45 +55 +55 diff --git a/dbms/tests/queries/0_stateless/00968_roundAge.sql b/dbms/tests/queries/0_stateless/00968_roundAge.sql new file mode 100644 index 00000000000..c8e5a5579f2 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00968_roundAge.sql @@ -0,0 +1,7 @@ +SELECT roundAge(0); +SELECT roundAge(18); +SELECT roundAge(25); +SELECT roundAge(35); +SELECT roundAge(45); +SELECT roundAge(55); +SELECT roundAge(56); \ No newline at end of file diff --git a/dbms/tests/queries/0_stateless/00969_roundDuration.reference b/dbms/tests/queries/0_stateless/00969_roundDuration.reference new file mode 100644 index 00000000000..463d6f92125 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00969_roundDuration.reference @@ -0,0 +1,16 @@ +0 +10 +30 +60 +120 +180 +240 +300 +600 +1200 +1800 +3600 +7200 +18000 +36000 +36000 diff --git a/dbms/tests/queries/0_stateless/00969_roundDuration.sql b/dbms/tests/queries/0_stateless/00969_roundDuration.sql new file mode 100644 index 00000000000..200ae2b78bd --- /dev/null +++ b/dbms/tests/queries/0_stateless/00969_roundDuration.sql @@ -0,0 +1,16 @@ +SELECT roundDuration(0); +SELECT roundDuration(10); +SELECT roundDuration(30); +SELECT roundDuration(60); +SELECT roundDuration(120); +SELECT roundDuration(180); +SELECT roundDuration(240); +SELECT roundDuration(300); +SELECT roundDuration(600); +SELECT roundDuration(1200); +SELECT roundDuration(1800); +SELECT roundDuration(3600); +SELECT roundDuration(7200); +SELECT roundDuration(18000); +SELECT roundDuration(36000); +SELECT roundDuration(37000); \ No newline at end of file diff --git a/dbms/tests/queries/0_stateless/00970_substring_arg_validation.reference b/dbms/tests/queries/0_stateless/00970_substring_arg_validation.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dbms/tests/queries/0_stateless/00970_substring_arg_validation.sql b/dbms/tests/queries/0_stateless/00970_substring_arg_validation.sql new file mode 100644 index 00000000000..7d8320a1d64 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00970_substring_arg_validation.sql @@ -0,0 +1,4 @@ +SELECT substring('hello', []); -- { serverError 43 } +SELECT substring('hello', 1, []); -- { serverError 43 } +SELECT substring(materialize('hello'), -1, -1); -- { serverError 69 } +SELECT substring(materialize('hello'), 0); -- { serverError 135 } \ No newline at end of file diff --git a/dbms/tests/queries/1_stateful/00037_uniq_state_merge1.reference b/dbms/tests/queries/1_stateful/00037_uniq_state_merge1.reference index d9ca7e3be21..3bedecd267b 100644 --- a/dbms/tests/queries/1_stateful/00037_uniq_state_merge1.reference +++ b/dbms/tests/queries/1_stateful/00037_uniq_state_merge1.reference @@ -1,24 +1,15 @@ -yandex.ru 25107 25107 - 21999 21999 -public_search 16749 16749 + 89348 89348 +yandex.ru 25105 25105 avito.ru 16523 16523 -public 15429 15429 -mail.yandex.ru 13663 13663 -yandsearch 10039 10039 -news 8827 8827 +mail.yandex.ru 13659 13659 mail.ru 7643 7643 -doc 7537 7537 auto.ru 7350 7350 hurpass.com 6395 6395 best.ru 5477 5477 tv.yandex.ru 5341 5341 korer.ru 4967 4967 -mail.yandsearch 4246 4246 -cars 4077 4077 -publ 3970 3970 -yandex 3845 3845 -main=hurriyet.com 3806 3806 -yandex.ua 3803 3803 +mail.yandsearch 4237 4237 +yandex.ua 3802 3802 korablitz.ru 3717 3717 uyelik.hurriyet.com 3584 3584 e.mail.ru 3508 3508 @@ -28,46 +19,32 @@ coccoc.com 2707 2707 rutube.ru 2699 2699 rbc.ru 2644 2644 mamba.ru 2598 2598 -video 2558 2558 -mail.yandex 2447 2447 -wot 2253 2253 +mail.yandex 2441 2441 pikabu.ru 2130 2130 yandex.php 2057 2057 e.mail.yandex.ru 1971 1971 brandex.ru 1969 1969 -bravoslava-230v 1942 1942 -search 1933 1933 market.ru 1913 1913 mynet.ru 1881 1881 -mail 1845 1845 -mail.yandex.ua 1825 1825 +mail.yandex.ua 1823 1823 rutube.com 1821 1821 -images 1812 1812 news.rambler.com 1787 1787 hurpass.com.tr 1763 1763 ads.search 1742 1742 -marina_2_sezon 1680 1680 cars.auto.ru 1628 1628 cian.ru 1620 1620 ivi.ru 1617 1617 av.by 1598 1598 -world 1596 1596 news.yandex.ru 1495 1495 vk.com 1474 1474 -pub 1469 1469 -forum 1414 1414 wow-girls.ru 1399 1399 -kinogo-dhpWXEdIcgoxWUZ6fgdTWw.. 1338 1338 uyelik.hurriyet.com.tr 1330 1330 aukro.ua 1314 1314 -plugins 1244 1244 images.yandsearch 1235 1235 ondom.ru 1221 1221 korablitz.com 1189 1189 -videovol-9-sezon 1187 1187 kerl.org 1155 1155 mail.yandex.php 1148 1148 -file 1147 1147 love.mail.yandex.ru 1136 1136 yandex.kz 1124 1124 coccoc.com.tr 1113 1113 @@ -77,24 +54,47 @@ sprashivai.ru 1072 1072 market.yandex.ru 1064 1064 spb-n.ru 1056 1056 sz.spaces.ru 1055 1055 -xofx.net%2F63857&secret-oper=reply&id=0&extras] 1054 1054 marinance.ua 1050 1050 tube.ru 1044 1044 haber.com 1043 1043 -image&img_url=http 1042 1042 -sport 1040 1040 megogo.net 993 993 sozcu.com 991 991 yandex.by 938 938 -image&uinfo 936 936 -fast-golove.mail.ru_Mobile=0&at=35&text=производств 927 927 -linka 901 901 gazeta.ru 892 892 -yandex.ru;yandex.ru 892 892 -kinogo-dhpWXEdIcgoxWUZ6fgdTXA.. 890 890 fotki.yandex.ru 875 875 fast-golove.mail.yandex.php 842 842 -news=previews 839 839 -faber 833 833 lenta.ru 820 820 publicdaroglundai_anketa.ru 813 813 +mail.yandex.kz 810 810 +censor.net 807 807 +mail.yandex.by 804 804 +nnn.ru 796 796 +maxi.su 788 788 +rambler.ru 755 755 +hurpass.com.ua 729 729 +g1.botva.lv 728 728 +m.sport.airway 724 724 +tvizle.com 723 723 +fast-golove.mail.yandex.ru 712 712 +spb.ru 693 693 +eksisozluk.com 689 689 +uyelik.hurriyet 666 666 +rst.ua 650 650 +deko.ru 647 647 +my.mail.yandex.ru 647 647 +astrov.pro 625 625 +yandsearch.php 624 624 +kinogo.net 617 617 +fanati-avtomobile.jsp 611 611 +tv.yandsearch 605 605 +soft.ru 603 603 +pluginplus.ru 601 601 +images.yandex 595 595 +1tv.rbc.ru 592 592 +ria.ru 591 591 +marina_prezideniz.hurriyet.com 578 578 +youtube.ru 575 575 +cars.autochno.ru 570 570 +a2.stars.auto.yandsearch 566 566 +love.mail.ru 560 560 +mail.rambler.ru 553 553 diff --git a/dbms/tests/queries/1_stateful/00038_uniq_state_merge2.reference b/dbms/tests/queries/1_stateful/00038_uniq_state_merge2.reference index 926cb1911ba..9144afd90b2 100644 --- a/dbms/tests/queries/1_stateful/00038_uniq_state_merge2.reference +++ b/dbms/tests/queries/1_stateful/00038_uniq_state_merge2.reference @@ -1,100 +1,100 @@ - 582035 80248 -ru 299420 71339 -com 78253 34500 -html 40288 19569 -ua 33160 18847 -tr 19570 13117 -net 19003 12908 -php 17817 12011 -yandsearch 13598 10329 -by 9349 7695 -yandex 8946 7282 -org 5897 5320 -tv 5371 4660 -kz 5175 4588 -aspx 3084 2800 -phtml 3012 2725 -xml 2993 2726 -tr&callback_url=http 2897 2681 -su 2833 2587 -shtml 2442 2218 -hurriyet 2030 1907 -search 1915 1904 -tr&user 1556 1494 -jpg 1531 1427 -tr&users 1449 1373 -tr&callback 1294 1244 -jsp 1083 1048 -net%2F63857&secret-oper=reply&id=0&extras] 1054 1054 -htm 957 921 -ru_Mobile=0&at=35&text=производств 927 927 -lv 916 910 -tr&user_page 916 885 -exe 911 891 -me 911 864 -tr&user_page=http 900 868 -do 864 838 -tr&used 782 768 -pro 778 772 +ru 262914 69218 + 92101 89421 +com 63298 30285 +ua 29037 17475 +html 25079 15039 +tr 16770 11857 +net 16387 11686 +php 14374 10307 +yandsearch 12024 9484 +by 8192 6915 +yandex 7211 6124 +org 4890 4514 +kz 4679 4211 +tv 4400 3928 +su 2602 2396 +phtml 2409 2226 +xml 2322 2182 +aspx 1959 1848 +search 1835 1827 +hurriyet 1385 1345 +shtml 995 966 +lv 879 875 +jsp 855 845 +exe 814 798 +pro 737 734 airway 724 724 -biz 685 672 -mail 677 660 -info 593 575 -tr&callback_url=https 534 526 -tr%2Fgaleri 533 522 +me 675 647 +jpg 662 647 +do 625 611 +mail 593 581 +biz 537 530 bstatistik_dlja-dlya-naches 521 521 -sx 498 496 -ru%2Fupload 497 492 -news 492 487 -hu 486 479 -aspx&referer 473 459 -pogoda 460 460 -auto 438 429 -az 434 425 -net%2F63857&secret=506d9e3dfbd268e6b6630e58 432 432 +info 461 453 +pogoda 459 459 +sx 450 449 +news 448 444 sportlibrary 431 431 -jpg,http 411 397 -tr&callbusiness 410 407 -fm 405 400 -online 401 399 -tr&callbusines 388 384 -ru%2Fnews 387 382 +hu 396 393 +htm 393 385 +fm 379 378 +online 374 372 bstatistic 366 366 -wbp 346 346 -am 336 333 -ru;yandsearch 330 328 -tr&user_page=https 330 328 -tr&callback_url 329 319 -html&lang=ru&lr=110&category=dressages%2Fcs306755 328 328 -pl 328 326 -blog 327 326 -jpg&pos 307 302 -bstana 305 305 -ru;yandex 287 284 -im 283 278 -diary 277 275 -slando 276 274 -eu 274 269 -to 271 269 -asp 253 250 -html&lang 253 248 -mynet 253 251 -tj 242 241 -sberbank 241 238 -haber 234 227 -jpg,https 232 232 -cc 226 221 -_2544 222 222 -ws 221 219 -mamba 220 220 +auto 363 355 +az 356 350 +wbp 343 343 +bstana 304 304 +blog 268 268 +diary 262 261 +am 260 258 +slando 254 252 +im 238 235 +eu 237 234 liveinteria 218 218 -tr%2Fanasayfa 215 210 -tr&user_pts=&states 213 213 -yandsearchplus 212 211 -jpg","photo 211 209 -ru%2Fwww 211 211 -com&callback_url=http 209 208 +to 215 213 +mamba 214 214 auto-supers 208 208 -co 206 205 -kg 206 205 -ru%2Fuploads 206 205 +sberbank 207 207 +tj 205 205 +bstatistik_dlja-dlya_avia 201 201 +bstanii_otryasam 200 200 +pl 200 198 +wroad_5d 200 200 +mynet 191 190 +bstan 187 187 +yandsearchplus 186 186 +haber 184 179 +jpg,https 184 184 +turkasovki 183 183 +co 177 177 +video 177 177 +gif","photos 175 175 +mgshared_zone 172 172 +wssp 172 172 +jpg,http 170 168 +swf 167 167 +cc 166 164 +ws 164 164 +kg 157 156 +mobili_s_probegom 154 153 +cgi 153 152 +yandsearcher 152 151 +uz 150 150 +nsf 149 149 +adriver 147 144 +slandsearch 143 142 +korrez 140 140 +bstatistik_dlja-dlja-putin 139 139 +rambler 133 132 +mvideo 132 132 +asp 129 128 +vc 127 127 +md 121 121 +jpg","photo 119 119 +mp4 118 117 +ee 116 115 +loveplaceOfSearchplus 111 111 +nl 111 111 +bstatistika 107 107 +br 102 102 +sport 99 99 diff --git a/dbms/tests/queries/1_stateful/00044_any_left_join_string.reference b/dbms/tests/queries/1_stateful/00044_any_left_join_string.reference index a96e3c9f457..364115011f9 100644 --- a/dbms/tests/queries/1_stateful/00044_any_left_join_string.reference +++ b/dbms/tests/queries/1_stateful/00044_any_left_join_string.reference @@ -1,10 +1,10 @@ + 4508153 712428 auto.ru 576845 8935 -yandex.ru 410788 111278 -public 328528 23 - 313516 26015 -public_search 311125 0 +yandex.ru 410776 111278 korer.ru 277987 0 avito.ru 163820 15556 -mail.yandex.ru 152469 1046 -main=hurriyet.com 152096 259 -wot 116912 6682 +mail.yandex.ru 152447 1046 +mail.ru 87949 22225 +best.ru 58537 55 +korablitz.ru 51844 0 +hurpass.com 49671 1251 diff --git a/dbms/tests/queries/1_stateful/00077_log_tinylog_stripelog.reference b/dbms/tests/queries/1_stateful/00077_log_tinylog_stripelog.reference index 98f50687de4..d8ccbd66592 100644 --- a/dbms/tests/queries/1_stateful/00077_log_tinylog_stripelog.reference +++ b/dbms/tests/queries/1_stateful/00077_log_tinylog_stripelog.reference @@ -1,10 +1,17 @@ -1 -1 -1 8873898 12457120258355519194 8873898 12457120258355519194 8873898 12457120258355519194 8873898 12457120258355519194 -1 -1 -1 +AdvEngineID.bin 1 +CounterID.bin 1 +RegionID.bin 1 +SearchPhrase.bin 1 +UserID.bin 1 +__marks.mrk 1 +AdvEngineID.bin 1 +CounterID.bin 1 +RegionID.bin 1 +SearchPhrase.bin 1 +UserID.bin 1 +data.bin 1 +index.mrk 1 diff --git a/dbms/tests/queries/1_stateful/00089_position_functions_with_non_constant_arg.reference b/dbms/tests/queries/1_stateful/00089_position_functions_with_non_constant_arg.reference index ad9a93d1113..4d0ba2b70f3 100644 --- a/dbms/tests/queries/1_stateful/00089_position_functions_with_non_constant_arg.reference +++ b/dbms/tests/queries/1_stateful/00089_position_functions_with_non_constant_arg.reference @@ -2,8 +2,5 @@ 0 0 0 -http://игры на передачи пригорька россия&lr=213&rpt=simage&uinfo=ww-1905-wh-643-fw-112-rossiisoft.in.ua%2FKievav@yandex?appkey=506d9e3dfbd268e6b6630e58 -http://игры на передачи пригорька россия&lr=213&rpt=simage&uinfo=ww-1905-wh-643-fw-112-rossiisoft.in.ua%2FKievav@yandex?appkey=506d9e3dfbd268e6b6630e58 -http://ru slovari 15 -https://ru spb.rabota 15 -https://e yandex 12 +https://povary_dlya-511-gemotedDynamo_accoshyutoy-s-kortosh@bk.ru/yandsearch?text=simages%2F8%2F10544998#posts%2Fkartofeleri +https://povary_dlya-511-gemotedDynamo_accoshyutoy-s-kortosh@bk.ru/yandsearch?text=simages%2F8%2F10544998#posts%2Fkartofeleri diff --git a/dbms/tests/queries/1_stateful/00151_replace_partition_with_different_granularity.reference b/dbms/tests/queries/1_stateful/00151_replace_partition_with_different_granularity.reference new file mode 100644 index 00000000000..31d3e6d14da --- /dev/null +++ b/dbms/tests/queries/1_stateful/00151_replace_partition_with_different_granularity.reference @@ -0,0 +1,3 @@ +8873898 +8873899 +8873899 diff --git a/dbms/tests/queries/1_stateful/00151_replace_partition_with_different_granularity.sql b/dbms/tests/queries/1_stateful/00151_replace_partition_with_different_granularity.sql new file mode 100644 index 00000000000..c907f353768 --- /dev/null +++ b/dbms/tests/queries/1_stateful/00151_replace_partition_with_different_granularity.sql @@ -0,0 +1,53 @@ +DROP TABLE IF EXISTS mixed_granularity_table; + +CREATE TABLE mixed_granularity_table (`WatchID` UInt64, `JavaEnable` UInt8, `Title` String, `GoodEvent` Int16, `EventTime` DateTime, `EventDate` Date, `CounterID` UInt32, `ClientIP` UInt32, `ClientIP6` FixedString(16), `RegionID` UInt32, `UserID` UInt64, `CounterClass` Int8, `OS` UInt8, `UserAgent` UInt8, `URL` String, `Referer` String, `URLDomain` String, `RefererDomain` String, `Refresh` UInt8, `IsRobot` UInt8, `RefererCategories` Array(UInt16), `URLCategories` Array(UInt16), `URLRegions` Array(UInt32), `RefererRegions` Array(UInt32), `ResolutionWidth` UInt16, `ResolutionHeight` UInt16, `ResolutionDepth` UInt8, `FlashMajor` UInt8, `FlashMinor` UInt8, `FlashMinor2` String, `NetMajor` UInt8, `NetMinor` UInt8, `UserAgentMajor` UInt16, `UserAgentMinor` FixedString(2), `CookieEnable` UInt8, `JavascriptEnable` UInt8, `IsMobile` UInt8, `MobilePhone` UInt8, `MobilePhoneModel` String, `Params` String, `IPNetworkID` UInt32, `TraficSourceID` Int8, `SearchEngineID` UInt16, `SearchPhrase` String, `AdvEngineID` UInt8, `IsArtifical` UInt8, `WindowClientWidth` UInt16, `WindowClientHeight` UInt16, `ClientTimeZone` Int16, `ClientEventTime` DateTime, `SilverlightVersion1` UInt8, `SilverlightVersion2` UInt8, `SilverlightVersion3` UInt32, `SilverlightVersion4` UInt16, `PageCharset` String, `CodeVersion` UInt32, `IsLink` UInt8, `IsDownload` UInt8, `IsNotBounce` UInt8, `FUniqID` UInt64, `HID` UInt32, `IsOldCounter` UInt8, `IsEvent` UInt8, `IsParameter` UInt8, `DontCountHits` UInt8, `WithHash` UInt8, `HitColor` FixedString(1), `UTCEventTime` DateTime, `Age` UInt8, `Sex` UInt8, `Income` UInt8, `Interests` UInt16, `Robotness` UInt8, `GeneralInterests` Array(UInt16), `RemoteIP` UInt32, `RemoteIP6` FixedString(16), `WindowName` Int32, `OpenerName` Int32, `HistoryLength` Int16, `BrowserLanguage` FixedString(2), `BrowserCountry` FixedString(2), `SocialNetwork` String, `SocialAction` String, `HTTPError` UInt16, `SendTiming` Int32, `DNSTiming` Int32, `ConnectTiming` Int32, `ResponseStartTiming` Int32, `ResponseEndTiming` Int32, `FetchTiming` Int32, `RedirectTiming` Int32, `DOMInteractiveTiming` Int32, `DOMContentLoadedTiming` Int32, `DOMCompleteTiming` Int32, `LoadEventStartTiming` Int32, `LoadEventEndTiming` Int32, `NSToDOMContentLoadedTiming` Int32, `FirstPaintTiming` Int32, `RedirectCount` Int8, `SocialSourceNetworkID` UInt8, `SocialSourcePage` String, `ParamPrice` Int64, `ParamOrderID` String, `ParamCurrency` FixedString(3), `ParamCurrencyID` UInt16, `GoalsReached` Array(UInt32), `OpenstatServiceName` String, `OpenstatCampaignID` String, `OpenstatAdID` String, `OpenstatSourceID` String, `UTMSource` String, `UTMMedium` String, `UTMCampaign` String, `UTMContent` String, `UTMTerm` String, `FromTag` String, `HasGCLID` UInt8, `RefererHash` UInt64, `URLHash` UInt64, `CLID` UInt32, `YCLID` UInt64, `ShareService` String, `ShareURL` String, `ShareTitle` String, `ParsedParams.Key1` Array(String), `ParsedParams.Key2` Array(String), `ParsedParams.Key3` Array(String), `ParsedParams.Key4` Array(String), `ParsedParams.Key5` Array(String), `ParsedParams.ValueDouble` Array(Float64), `IslandID` FixedString(16), `RequestNum` UInt32, `RequestTry` UInt8) ENGINE = MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID) SETTINGS index_granularity=8192, enable_mixed_granularity_parts=1; -- same with hits, but enabled mixed granularity + +INSERT INTO mixed_granularity_table SELECT * FROM test.hits LIMIT 10; + +ALTER TABLE mixed_granularity_table REPLACE PARTITION 201403 FROM test.hits; + +SELECT COUNT() FROM mixed_granularity_table; + +INSERT INTO mixed_granularity_table SELECT * FROM test.hits LIMIT 1; + +SELECT COUNT() FROM mixed_granularity_table; + +OPTIMIZE TABLE mixed_granularity_table FINAL; + +SELECT COUNT() FROM mixed_granularity_table; + +-- check strange cases when we try to replace parts from another tables but with different granularity settings + +DROP TABLE IF EXISTS non_mixed_granularity_adaptive_table; + +CREATE TABLE non_mixed_granularity_adaptive_table AS test.hits; + +INSERT INTO non_mixed_granularity_adaptive_table SELECT * FROM test.hits LIMIT 10; + +ALTER TABLE non_mixed_granularity_adaptive_table REPLACE PARTITION 201403 FROM test.hits; -- { serverError 49 } + +DROP TABLE IF EXISTS non_mixed_granularity_adaptive_table; + +DROP TABLE IF EXISTS non_mixed_granularity_non_adaptive_table; + +CREATE TABLE non_mixed_granularity_non_adaptive_table (`WatchID` UInt64, `JavaEnable` UInt8, `Title` String, `GoodEvent` Int16, `EventTime` DateTime, `EventDate` Date, `CounterID` UInt32, `ClientIP` UInt32, `ClientIP6` FixedString(16), `RegionID` UInt32, `UserID` UInt64, `CounterClass` Int8, `OS` UInt8, `UserAgent` UInt8, `URL` String, `Referer` String, `URLDomain` String, `RefererDomain` String, `Refresh` UInt8, `IsRobot` UInt8, `RefererCategories` Array(UInt16), `URLCategories` Array(UInt16), `URLRegions` Array(UInt32), `RefererRegions` Array(UInt32), `ResolutionWidth` UInt16, `ResolutionHeight` UInt16, `ResolutionDepth` UInt8, `FlashMajor` UInt8, `FlashMinor` UInt8, `FlashMinor2` String, `NetMajor` UInt8, `NetMinor` UInt8, `UserAgentMajor` UInt16, `UserAgentMinor` FixedString(2), `CookieEnable` UInt8, `JavascriptEnable` UInt8, `IsMobile` UInt8, `MobilePhone` UInt8, `MobilePhoneModel` String, `Params` String, `IPNetworkID` UInt32, `TraficSourceID` Int8, `SearchEngineID` UInt16, `SearchPhrase` String, `AdvEngineID` UInt8, `IsArtifical` UInt8, `WindowClientWidth` UInt16, `WindowClientHeight` UInt16, `ClientTimeZone` Int16, `ClientEventTime` DateTime, `SilverlightVersion1` UInt8, `SilverlightVersion2` UInt8, `SilverlightVersion3` UInt32, `SilverlightVersion4` UInt16, `PageCharset` String, `CodeVersion` UInt32, `IsLink` UInt8, `IsDownload` UInt8, `IsNotBounce` UInt8, `FUniqID` UInt64, `HID` UInt32, `IsOldCounter` UInt8, `IsEvent` UInt8, `IsParameter` UInt8, `DontCountHits` UInt8, `WithHash` UInt8, `HitColor` FixedString(1), `UTCEventTime` DateTime, `Age` UInt8, `Sex` UInt8, `Income` UInt8, `Interests` UInt16, `Robotness` UInt8, `GeneralInterests` Array(UInt16), `RemoteIP` UInt32, `RemoteIP6` FixedString(16), `WindowName` Int32, `OpenerName` Int32, `HistoryLength` Int16, `BrowserLanguage` FixedString(2), `BrowserCountry` FixedString(2), `SocialNetwork` String, `SocialAction` String, `HTTPError` UInt16, `SendTiming` Int32, `DNSTiming` Int32, `ConnectTiming` Int32, `ResponseStartTiming` Int32, `ResponseEndTiming` Int32, `FetchTiming` Int32, `RedirectTiming` Int32, `DOMInteractiveTiming` Int32, `DOMContentLoadedTiming` Int32, `DOMCompleteTiming` Int32, `LoadEventStartTiming` Int32, `LoadEventEndTiming` Int32, `NSToDOMContentLoadedTiming` Int32, `FirstPaintTiming` Int32, `RedirectCount` Int8, `SocialSourceNetworkID` UInt8, `SocialSourcePage` String, `ParamPrice` Int64, `ParamOrderID` String, `ParamCurrency` FixedString(3), `ParamCurrencyID` UInt16, `GoalsReached` Array(UInt32), `OpenstatServiceName` String, `OpenstatCampaignID` String, `OpenstatAdID` String, `OpenstatSourceID` String, `UTMSource` String, `UTMMedium` String, `UTMCampaign` String, `UTMContent` String, `UTMTerm` String, `FromTag` String, `HasGCLID` UInt8, `RefererHash` UInt64, `URLHash` UInt64, `CLID` UInt32, `YCLID` UInt64, `ShareService` String, `ShareURL` String, `ShareTitle` String, `ParsedParams.Key1` Array(String), `ParsedParams.Key2` Array(String), `ParsedParams.Key3` Array(String), `ParsedParams.Key4` Array(String), `ParsedParams.Key5` Array(String), `ParsedParams.ValueDouble` Array(Float64), `IslandID` FixedString(16), `RequestNum` UInt32, `RequestTry` UInt8) ENGINE = MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID) SETTINGS index_granularity=8192, index_granularity_bytes=0; -- same with hits, but enabled mixed granularity and fixed_granularity + +INSERT INTO non_mixed_granularity_non_adaptive_table SELECT * FROM test.hits LIMIT 10; + +-- after optimize mixed_granularity_table will have .mrk2 parts +ALTER TABLE non_mixed_granularity_non_adaptive_table REPLACE PARTITION 201403 FROM mixed_granularity_table; -- { serverError 49 } + +DROP TABLE IF EXISTS non_mixed_granularity_non_adaptive_table; + + +DROP TABLE IF EXISTS mixed_granularity_strictly_non_adaptive_table; + +CREATE TABLE mixed_granularity_strictly_non_adaptive_table (`WatchID` UInt64, `JavaEnable` UInt8, `Title` String, `GoodEvent` Int16, `EventTime` DateTime, `EventDate` Date, `CounterID` UInt32, `ClientIP` UInt32, `ClientIP6` FixedString(16), `RegionID` UInt32, `UserID` UInt64, `CounterClass` Int8, `OS` UInt8, `UserAgent` UInt8, `URL` String, `Referer` String, `URLDomain` String, `RefererDomain` String, `Refresh` UInt8, `IsRobot` UInt8, `RefererCategories` Array(UInt16), `URLCategories` Array(UInt16), `URLRegions` Array(UInt32), `RefererRegions` Array(UInt32), `ResolutionWidth` UInt16, `ResolutionHeight` UInt16, `ResolutionDepth` UInt8, `FlashMajor` UInt8, `FlashMinor` UInt8, `FlashMinor2` String, `NetMajor` UInt8, `NetMinor` UInt8, `UserAgentMajor` UInt16, `UserAgentMinor` FixedString(2), `CookieEnable` UInt8, `JavascriptEnable` UInt8, `IsMobile` UInt8, `MobilePhone` UInt8, `MobilePhoneModel` String, `Params` String, `IPNetworkID` UInt32, `TraficSourceID` Int8, `SearchEngineID` UInt16, `SearchPhrase` String, `AdvEngineID` UInt8, `IsArtifical` UInt8, `WindowClientWidth` UInt16, `WindowClientHeight` UInt16, `ClientTimeZone` Int16, `ClientEventTime` DateTime, `SilverlightVersion1` UInt8, `SilverlightVersion2` UInt8, `SilverlightVersion3` UInt32, `SilverlightVersion4` UInt16, `PageCharset` String, `CodeVersion` UInt32, `IsLink` UInt8, `IsDownload` UInt8, `IsNotBounce` UInt8, `FUniqID` UInt64, `HID` UInt32, `IsOldCounter` UInt8, `IsEvent` UInt8, `IsParameter` UInt8, `DontCountHits` UInt8, `WithHash` UInt8, `HitColor` FixedString(1), `UTCEventTime` DateTime, `Age` UInt8, `Sex` UInt8, `Income` UInt8, `Interests` UInt16, `Robotness` UInt8, `GeneralInterests` Array(UInt16), `RemoteIP` UInt32, `RemoteIP6` FixedString(16), `WindowName` Int32, `OpenerName` Int32, `HistoryLength` Int16, `BrowserLanguage` FixedString(2), `BrowserCountry` FixedString(2), `SocialNetwork` String, `SocialAction` String, `HTTPError` UInt16, `SendTiming` Int32, `DNSTiming` Int32, `ConnectTiming` Int32, `ResponseStartTiming` Int32, `ResponseEndTiming` Int32, `FetchTiming` Int32, `RedirectTiming` Int32, `DOMInteractiveTiming` Int32, `DOMContentLoadedTiming` Int32, `DOMCompleteTiming` Int32, `LoadEventStartTiming` Int32, `LoadEventEndTiming` Int32, `NSToDOMContentLoadedTiming` Int32, `FirstPaintTiming` Int32, `RedirectCount` Int8, `SocialSourceNetworkID` UInt8, `SocialSourcePage` String, `ParamPrice` Int64, `ParamOrderID` String, `ParamCurrency` FixedString(3), `ParamCurrencyID` UInt16, `GoalsReached` Array(UInt32), `OpenstatServiceName` String, `OpenstatCampaignID` String, `OpenstatAdID` String, `OpenstatSourceID` String, `UTMSource` String, `UTMMedium` String, `UTMCampaign` String, `UTMContent` String, `UTMTerm` String, `FromTag` String, `HasGCLID` UInt8, `RefererHash` UInt64, `URLHash` UInt64, `CLID` UInt32, `YCLID` UInt64, `ShareService` String, `ShareURL` String, `ShareTitle` String, `ParsedParams.Key1` Array(String), `ParsedParams.Key2` Array(String), `ParsedParams.Key3` Array(String), `ParsedParams.Key4` Array(String), `ParsedParams.Key5` Array(String), `ParsedParams.ValueDouble` Array(Float64), `IslandID` FixedString(16), `RequestNum` UInt32, `RequestTry` UInt8) ENGINE = MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID) SETTINGS index_granularity=8192, enable_mixed_granularity_parts=1, index_granularity_bytes=0; -- same with hits, but enabled mixed granularity and fixed_granularity + +INSERT INTO mixed_granularity_strictly_non_adaptive_table SELECT * FROM test.hits LIMIT 10; + +ALTER TABLE mixed_granularity_strictly_non_adaptive_table REPLACE PARTITION 201403 FROM mixed_granularity_table; -- { serverError 49 } + +DROP TABLE IF EXISTS mixed_granularity_table; + +DROP TABLE IF EXISTS mixed_granularity_strictly_non_adaptive_table; diff --git a/dbms/tests/queries/1_stateful/00152_insert_different_granularity.reference b/dbms/tests/queries/1_stateful/00152_insert_different_granularity.reference new file mode 100644 index 00000000000..c573f1c3072 --- /dev/null +++ b/dbms/tests/queries/1_stateful/00152_insert_different_granularity.reference @@ -0,0 +1,2 @@ +8873918 +8873998 diff --git a/dbms/tests/queries/1_stateful/00152_insert_different_granularity.sql b/dbms/tests/queries/1_stateful/00152_insert_different_granularity.sql new file mode 100644 index 00000000000..e690daadb6e --- /dev/null +++ b/dbms/tests/queries/1_stateful/00152_insert_different_granularity.sql @@ -0,0 +1,49 @@ +DROP TABLE IF EXISTS fixed_granularity_table; + +CREATE TABLE fixed_granularity_table (`WatchID` UInt64, `JavaEnable` UInt8, `Title` String, `GoodEvent` Int16, `EventTime` DateTime, `EventDate` Date, `CounterID` UInt32, `ClientIP` UInt32, `ClientIP6` FixedString(16), `RegionID` UInt32, `UserID` UInt64, `CounterClass` Int8, `OS` UInt8, `UserAgent` UInt8, `URL` String, `Referer` String, `URLDomain` String, `RefererDomain` String, `Refresh` UInt8, `IsRobot` UInt8, `RefererCategories` Array(UInt16), `URLCategories` Array(UInt16), `URLRegions` Array(UInt32), `RefererRegions` Array(UInt32), `ResolutionWidth` UInt16, `ResolutionHeight` UInt16, `ResolutionDepth` UInt8, `FlashMajor` UInt8, `FlashMinor` UInt8, `FlashMinor2` String, `NetMajor` UInt8, `NetMinor` UInt8, `UserAgentMajor` UInt16, `UserAgentMinor` FixedString(2), `CookieEnable` UInt8, `JavascriptEnable` UInt8, `IsMobile` UInt8, `MobilePhone` UInt8, `MobilePhoneModel` String, `Params` String, `IPNetworkID` UInt32, `TraficSourceID` Int8, `SearchEngineID` UInt16, `SearchPhrase` String, `AdvEngineID` UInt8, `IsArtifical` UInt8, `WindowClientWidth` UInt16, `WindowClientHeight` UInt16, `ClientTimeZone` Int16, `ClientEventTime` DateTime, `SilverlightVersion1` UInt8, `SilverlightVersion2` UInt8, `SilverlightVersion3` UInt32, `SilverlightVersion4` UInt16, `PageCharset` String, `CodeVersion` UInt32, `IsLink` UInt8, `IsDownload` UInt8, `IsNotBounce` UInt8, `FUniqID` UInt64, `HID` UInt32, `IsOldCounter` UInt8, `IsEvent` UInt8, `IsParameter` UInt8, `DontCountHits` UInt8, `WithHash` UInt8, `HitColor` FixedString(1), `UTCEventTime` DateTime, `Age` UInt8, `Sex` UInt8, `Income` UInt8, `Interests` UInt16, `Robotness` UInt8, `GeneralInterests` Array(UInt16), `RemoteIP` UInt32, `RemoteIP6` FixedString(16), `WindowName` Int32, `OpenerName` Int32, `HistoryLength` Int16, `BrowserLanguage` FixedString(2), `BrowserCountry` FixedString(2), `SocialNetwork` String, `SocialAction` String, `HTTPError` UInt16, `SendTiming` Int32, `DNSTiming` Int32, `ConnectTiming` Int32, `ResponseStartTiming` Int32, `ResponseEndTiming` Int32, `FetchTiming` Int32, `RedirectTiming` Int32, `DOMInteractiveTiming` Int32, `DOMContentLoadedTiming` Int32, `DOMCompleteTiming` Int32, `LoadEventStartTiming` Int32, `LoadEventEndTiming` Int32, `NSToDOMContentLoadedTiming` Int32, `FirstPaintTiming` Int32, `RedirectCount` Int8, `SocialSourceNetworkID` UInt8, `SocialSourcePage` String, `ParamPrice` Int64, `ParamOrderID` String, `ParamCurrency` FixedString(3), `ParamCurrencyID` UInt16, `GoalsReached` Array(UInt32), `OpenstatServiceName` String, `OpenstatCampaignID` String, `OpenstatAdID` String, `OpenstatSourceID` String, `UTMSource` String, `UTMMedium` String, `UTMCampaign` String, `UTMContent` String, `UTMTerm` String, `FromTag` String, `HasGCLID` UInt8, `RefererHash` UInt64, `URLHash` UInt64, `CLID` UInt32, `YCLID` UInt64, `ShareService` String, `ShareURL` String, `ShareTitle` String, `ParsedParams.Key1` Array(String), `ParsedParams.Key2` Array(String), `ParsedParams.Key3` Array(String), `ParsedParams.Key4` Array(String), `ParsedParams.Key5` Array(String), `ParsedParams.ValueDouble` Array(Float64), `IslandID` FixedString(16), `RequestNum` UInt32, `RequestTry` UInt8) ENGINE = MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID) SETTINGS index_granularity=8192, index_granularity_bytes=0; -- looks like default table before update + +ALTER TABLE fixed_granularity_table REPLACE PARTITION 201403 FROM test.hits; + +INSERT INTO fixed_granularity_table SELECT * FROM test.hits LIMIT 10; -- should still have non adaptive granularity + +INSERT INTO fixed_granularity_table SELECT * FROM test.hits LIMIT 10; + +OPTIMIZE TABLE fixed_granularity_table FINAL; -- and even after optimize + +DETACH TABLE fixed_granularity_table; + +ATTACH TABLE fixed_granularity_table; + +ALTER TABLE fixed_granularity_table DETACH PARTITION 201403; + +ALTER TABLE fixed_granularity_table ATTACH PARTITION 201403; + +SELECT count() from fixed_granularity_table; + +DROP TABLE IF EXISTS fixed_granularity_table; + +ALTER TABLE test.hits DETACH PARTITION 201403; + +ALTER TABLE test.hits ATTACH PARTITION 201403; + +DROP TABLE IF EXISTS hits_copy; + +CREATE TABLE hits_copy (`WatchID` UInt64, `JavaEnable` UInt8, `Title` String, `GoodEvent` Int16, `EventTime` DateTime, `EventDate` Date, `CounterID` UInt32, `ClientIP` UInt32, `ClientIP6` FixedString(16), `RegionID` UInt32, `UserID` UInt64, `CounterClass` Int8, `OS` UInt8, `UserAgent` UInt8, `URL` String, `Referer` String, `URLDomain` String, `RefererDomain` String, `Refresh` UInt8, `IsRobot` UInt8, `RefererCategories` Array(UInt16), `URLCategories` Array(UInt16), `URLRegions` Array(UInt32), `RefererRegions` Array(UInt32), `ResolutionWidth` UInt16, `ResolutionHeight` UInt16, `ResolutionDepth` UInt8, `FlashMajor` UInt8, `FlashMinor` UInt8, `FlashMinor2` String, `NetMajor` UInt8, `NetMinor` UInt8, `UserAgentMajor` UInt16, `UserAgentMinor` FixedString(2), `CookieEnable` UInt8, `JavascriptEnable` UInt8, `IsMobile` UInt8, `MobilePhone` UInt8, `MobilePhoneModel` String, `Params` String, `IPNetworkID` UInt32, `TraficSourceID` Int8, `SearchEngineID` UInt16, `SearchPhrase` String, `AdvEngineID` UInt8, `IsArtifical` UInt8, `WindowClientWidth` UInt16, `WindowClientHeight` UInt16, `ClientTimeZone` Int16, `ClientEventTime` DateTime, `SilverlightVersion1` UInt8, `SilverlightVersion2` UInt8, `SilverlightVersion3` UInt32, `SilverlightVersion4` UInt16, `PageCharset` String, `CodeVersion` UInt32, `IsLink` UInt8, `IsDownload` UInt8, `IsNotBounce` UInt8, `FUniqID` UInt64, `HID` UInt32, `IsOldCounter` UInt8, `IsEvent` UInt8, `IsParameter` UInt8, `DontCountHits` UInt8, `WithHash` UInt8, `HitColor` FixedString(1), `UTCEventTime` DateTime, `Age` UInt8, `Sex` UInt8, `Income` UInt8, `Interests` UInt16, `Robotness` UInt8, `GeneralInterests` Array(UInt16), `RemoteIP` UInt32, `RemoteIP6` FixedString(16), `WindowName` Int32, `OpenerName` Int32, `HistoryLength` Int16, `BrowserLanguage` FixedString(2), `BrowserCountry` FixedString(2), `SocialNetwork` String, `SocialAction` String, `HTTPError` UInt16, `SendTiming` Int32, `DNSTiming` Int32, `ConnectTiming` Int32, `ResponseStartTiming` Int32, `ResponseEndTiming` Int32, `FetchTiming` Int32, `RedirectTiming` Int32, `DOMInteractiveTiming` Int32, `DOMContentLoadedTiming` Int32, `DOMCompleteTiming` Int32, `LoadEventStartTiming` Int32, `LoadEventEndTiming` Int32, `NSToDOMContentLoadedTiming` Int32, `FirstPaintTiming` Int32, `RedirectCount` Int8, `SocialSourceNetworkID` UInt8, `SocialSourcePage` String, `ParamPrice` Int64, `ParamOrderID` String, `ParamCurrency` FixedString(3), `ParamCurrencyID` UInt16, `GoalsReached` Array(UInt32), `OpenstatServiceName` String, `OpenstatCampaignID` String, `OpenstatAdID` String, `OpenstatSourceID` String, `UTMSource` String, `UTMMedium` String, `UTMCampaign` String, `UTMContent` String, `UTMTerm` String, `FromTag` String, `HasGCLID` UInt8, `RefererHash` UInt64, `URLHash` UInt64, `CLID` UInt32, `YCLID` UInt64, `ShareService` String, `ShareURL` String, `ShareTitle` String, `ParsedParams.Key1` Array(String), `ParsedParams.Key2` Array(String), `ParsedParams.Key3` Array(String), `ParsedParams.Key4` Array(String), `ParsedParams.Key5` Array(String), `ParsedParams.ValueDouble` Array(Float64), `IslandID` FixedString(16), `RequestNum` UInt32, `RequestTry` UInt8) ENGINE = MergeTree() PARTITION BY toYYYYMM(EventDate) ORDER BY (CounterID, EventDate, intHash32(UserID)) SAMPLE BY intHash32(UserID) SETTINGS index_granularity=8192, index_granularity_bytes=0; + +ALTER TABLE hits_copy REPLACE PARTITION 201403 FROM test.hits; + +-- It's important to test table, which were created before server update +INSERT INTO test.hits SELECT * FROM hits_copy LIMIT 100; + +ALTER TABLE test.hits DETACH PARTITION 201403; + +ALTER TABLE test.hits ATTACH PARTITION 201403; + +OPTIMIZE TABLE test.hits; + +SELECT count() FROM test.hits; + +-- restore hits +ALTER TABLE test.hits REPLACE PARTITION 201403 FROM hits_copy; + +DROP TABLE IF EXISTS hits_copy; diff --git a/debian/changelog b/debian/changelog index 52ac759a110..6abe0effc06 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -clickhouse (19.11.0) unstable; urgency=low +clickhouse (19.12.1.1) unstable; urgency=low * Modified source code - -- chertus Fri, 21 Jun 2019 18:47:02 +0300 + -- clickhouse-release Wed, 10 Jul 2019 22:57:50 +0300 diff --git a/debian/clickhouse-server.postinst b/debian/clickhouse-server.postinst index cd1590258ce..944b1e394f1 100644 --- a/debian/clickhouse-server.postinst +++ b/debian/clickhouse-server.postinst @@ -121,9 +121,9 @@ Please fix this and reinstall this package." >&2 TMPFILE=/tmp/test_setcap.sh command -v setcap >/dev/null \ - && echo > $TMPFILE && chmod a+x $TMPFILE && $TMPFILE && setcap "cap_net_admin,cap_ipc_lock+ep" $TMPFILE && $TMPFILE && rm $TMPFILE \ - && setcap "cap_net_admin,cap_ipc_lock+ep" "${CLICKHOUSE_BINDIR}/${CLICKHOUSE_GENERIC_PROGRAM}" \ - || echo "Cannot set 'net_admin' or 'ipc_lock' capability for clickhouse binary. This is optional. Taskstats accounting will be disabled. To enable taskstats accounting you may add the required capability later manually." + && echo > $TMPFILE && chmod a+x $TMPFILE && $TMPFILE && setcap "cap_net_admin,cap_ipc_lock,cap_sys_nice+ep" $TMPFILE && $TMPFILE && rm $TMPFILE \ + && setcap "cap_net_admin,cap_ipc_lock,cap_sys_nice+ep" "${CLICKHOUSE_BINDIR}/${CLICKHOUSE_GENERIC_PROGRAM}" \ + || echo "Cannot set 'net_admin' or 'ipc_lock' or 'sys_nice' capability for clickhouse binary. This is optional. Taskstats accounting will be disabled. To enable taskstats accounting you may add the required capability later manually." # Clean old dynamic compilation results if [ -d "${CLICKHOUSE_DATADIR_FROM_CONFIG}/build" ]; then diff --git a/debian/clickhouse-server.service b/debian/clickhouse-server.service index 7eaceeab986..4543b304197 100644 --- a/debian/clickhouse-server.service +++ b/debian/clickhouse-server.service @@ -11,7 +11,7 @@ RuntimeDirectory=clickhouse-server ExecStart=/usr/bin/clickhouse-server --config=/etc/clickhouse-server/config.xml --pid-file=/run/clickhouse-server/clickhouse-server.pid LimitCORE=infinity LimitNOFILE=500000 -CapabilityBoundingSet=CAP_NET_ADMIN CAP_IPC_LOCK +CapabilityBoundingSet=CAP_NET_ADMIN CAP_IPC_LOCK CAP_SYS_NICE [Install] WantedBy=multi-user.target diff --git a/docker/client/Dockerfile b/docker/client/Dockerfile index c6af86c5825..1afc097aafd 100644 --- a/docker/client/Dockerfile +++ b/docker/client/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu:18.04 ARG repository="deb http://repo.yandex.ru/clickhouse/deb/stable/ main/" -ARG version=19.11.0 +ARG version=19.12.1.* RUN apt-get update \ && apt-get install --yes --no-install-recommends \ diff --git a/docker/images.json b/docker/images.json index 6ab12504a7d..e2282fcb653 100644 --- a/docker/images.json +++ b/docker/images.json @@ -7,7 +7,9 @@ "docker/test/performance": "yandex/clickhouse-performance-test", "docker/test/pvs": "yandex/clickhouse-pvs-test", "docker/test/stateful": "yandex/clickhouse-stateful-test", + "docker/test/stateful_with_coverage": "yandex/clickhouse-stateful-with-coverage-test", "docker/test/stateless": "yandex/clickhouse-stateless-test", + "docker/test/stateless_with_coverage": "yandex/clickhouse-stateless-with-coverage-test", "docker/test/unit": "yandex/clickhouse-unit-test", "docker/test/stress": "yandex/clickhouse-stress-test", "dbms/tests/integration/image": "yandex/clickhouse-integration-tests-runner" diff --git a/docker/packager/deb/Dockerfile b/docker/packager/deb/Dockerfile index eb67fd52cb8..0c9c82a5e1f 100644 --- a/docker/packager/deb/Dockerfile +++ b/docker/packager/deb/Dockerfile @@ -70,6 +70,5 @@ RUN apt-get --allow-unauthenticated update -y \ gperf \ alien - COPY build.sh / CMD ["/bin/bash", "/build.sh"] diff --git a/docker/packager/packager b/docker/packager/packager index 9dadb96b46d..0e8bf6ea98d 100755 --- a/docker/packager/packager +++ b/docker/packager/packager @@ -103,7 +103,7 @@ def run_vagrant_box_with_env(image_path, output_dir, ch_root): logging.info("Copying binary back") vagrant.copy_from_image("~/ClickHouse/dbms/programs/clickhouse", output_dir) -def parse_env_variables(build_type, compiler, sanitizer, package_type, cache, distcc_hosts, unbundled, split_binary, version, author, official, alien_pkgs): +def parse_env_variables(build_type, compiler, sanitizer, package_type, cache, distcc_hosts, unbundled, split_binary, version, author, official, alien_pkgs, with_coverage): result = [] cmake_flags = ['$CMAKE_FLAGS'] @@ -146,7 +146,10 @@ def parse_env_variables(build_type, compiler, sanitizer, package_type, cache, di cmake_flags.append('-DUNBUNDLED=1 -DENABLE_MYSQL=0 -DENABLE_POCO_ODBC=0 -DENABLE_ODBC=0') if split_binary: - cmake_flags.append('-DUSE_STATIC_LIBRARIES=0 -DSPLIT_SHARED_LIBRARIES=1 -DCLICKHOUSE_SPLIT_BINARY=1') + cmake_flags.append('-DUSE_STATIC_LIBRARIES=0 -DSPLIT_SHARED_LIBRARIES=1 -DCLICKHOUSE_SPLIT_BINARY=1 -DGLIBC_COMPATIBILITY=ON') + + if with_coverage: + cmake_flags.append('-DWITH_COVERAGE=1') if version: result.append("VERSION_STRING='{}'".format(version)) @@ -180,6 +183,7 @@ if __name__ == "__main__": parser.add_argument("--author", default="clickhouse") parser.add_argument("--official", action="store_true") parser.add_argument("--alien-pkgs", nargs='+', default=[]) + parser.add_argument("--with-coverage", action="store_true") args = parser.parse_args() if not os.path.isabs(args.output_dir): @@ -202,7 +206,7 @@ if __name__ == "__main__": env_prepared = parse_env_variables( args.build_type, args.compiler, args.sanitizer, args.package_type, args.cache, args.distcc_hosts, args.unbundled, args.split_binary, - args.version, args.author, args.official, args.alien_pkgs) + args.version, args.author, args.official, args.alien_pkgs, args.with_coverage) if args.package_type != "freebsd": run_docker_image_with_env(image_name, args.output_dir, env_prepared, ch_root, args.ccache_dir) else: diff --git a/docker/server/Dockerfile b/docker/server/Dockerfile index 879a9cd8c59..fed4295b76c 100644 --- a/docker/server/Dockerfile +++ b/docker/server/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu:18.04 ARG repository="deb http://repo.yandex.ru/clickhouse/deb/stable/ main/" -ARG version=19.11.0 +ARG version=19.12.1.* ARG gosu_ver=1.10 RUN apt-get update \ diff --git a/docker/test/Dockerfile b/docker/test/Dockerfile index 9743ec8624c..488a2554483 100644 --- a/docker/test/Dockerfile +++ b/docker/test/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu:18.04 ARG repository="deb http://repo.yandex.ru/clickhouse/deb/stable/ main/" -ARG version=19.11.0 +ARG version=19.12.1.* RUN apt-get update && \ apt-get install -y apt-transport-https dirmngr && \ diff --git a/docker/test/coverage/Dockerfile b/docker/test/coverage/Dockerfile new file mode 100644 index 00000000000..c0c31a42571 --- /dev/null +++ b/docker/test/coverage/Dockerfile @@ -0,0 +1,36 @@ +# docker build -t yandex/clickhouse-coverage . +FROM yandex/clickhouse-deb-builder + +RUN apt-get --allow-unauthenticated update -y \ + && env DEBIAN_FRONTEND=noninteractive \ + apt-get --allow-unauthenticated install --yes --no-install-recommends \ + bash \ + fakeroot \ + cmake \ + ccache \ + curl \ + software-properties-common + + +RUN echo "deb [trusted=yes] http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" >> /etc/apt/sources.list + +RUN apt-get --allow-unauthenticated update -y \ + && env DEBIAN_FRONTEND=noninteractive \ + apt-get --allow-unauthenticated install --yes --no-install-recommends \ + perl \ + lcov \ + llvm-9 \ + tzdata + + +ENV COVERAGE_DIR=/coverage_reports +ENV SOURCE_DIR=/build +ENV OUTPUT_DIR=/output +ENV IGNORE='.*contrib.*' + + +CMD mkdir -p /build/obj-x86_64-linux-gnu && cd /build/obj-x86_64-linux-gnu && CC=clang-7 CXX=clang++-7 cmake .. && cd /; \ + dpkg -i /package_folder/clickhouse-common-static_*.deb; \ + llvm-profdata-9 merge -sparse ${COVERAGE_DIR}/* -o clickhouse.profdata && \ + llvm-cov-9 export /usr/bin/clickhouse -instr-profile=clickhouse.profdata -j=16 -format=lcov -skip-functions -ignore-filename-regex $IGNORE > output.lcov && \ + genhtml output.lcov --ignore-errors source --output-directory ${OUTPUT_DIR} diff --git a/docker/test/integration/Dockerfile b/docker/test/integration/Dockerfile index d582247db74..c5f4629ba72 100644 --- a/docker/test/integration/Dockerfile +++ b/docker/test/integration/Dockerfile @@ -1,8 +1,10 @@ # docker build -t yandex/clickhouse-integration-test . FROM ubuntu:18.04 +RUN echo "deb [trusted=yes] http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main" >> /etc/apt/sources.list + RUN apt-get update \ - && env DEBIAN_FRONTEND=noninteractive apt-get -y install tzdata python llvm-6.0 llvm-6.0-dev libreadline-dev libicu-dev bsdutils \ + && env DEBIAN_FRONTEND=noninteractive apt-get -y install tzdata python llvm-6.0 llvm-6.0-dev libreadline-dev libicu-dev bsdutils llvm-8 \ && rm -rf \ /var/lib/apt/lists/* \ /var/cache/debconf \ @@ -15,5 +17,6 @@ RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN echo "TSAN_OPTIONS='halt_on_error=1 history_size=7'" >> /etc/environment; \ echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment; \ echo "ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \ + echo "TSAN_SYMBOLIZER_PATH=/usr/lib/llvm-8/bin/llvm-symbolizer" >> /etc/environment; \ echo "UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \ echo "LLVM_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; diff --git a/docker/test/stateful/Dockerfile b/docker/test/stateful/Dockerfile index 65943bf6955..466578c8b98 100644 --- a/docker/test/stateful/Dockerfile +++ b/docker/test/stateful/Dockerfile @@ -16,8 +16,16 @@ CMD dpkg -i package_folder/clickhouse-common-static_*.deb; \ dpkg -i package_folder/clickhouse-server_*.deb; \ dpkg -i package_folder/clickhouse-client_*.deb; \ dpkg -i package_folder/clickhouse-test_*.deb; \ + ln -s /usr/share/clickhouse-test/config/zookeeper.xml /etc/clickhouse-server/config.d/; \ + ln -s /usr/share/clickhouse-test/config/listen.xml /etc/clickhouse-server/config.d/; \ + ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/; \ + ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/; \ + ln -s /usr/share/clickhouse-test/config/readonly.xml /etc/clickhouse-server/users.d/; \ + ln -s /usr/share/clickhouse-test/config/ints_dictionary.xml /etc/clickhouse-server/; \ + ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/; \ + ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/; \ ln -s /usr/lib/llvm-8/bin/llvm-symbolizer /usr/bin/llvm-symbolizer; \ - echo "TSAN_OPTIONS='halt_on_error=1 history_size=7'" >> /etc/environment; \ + echo "TSAN_OPTIONS='verbosity=1000 halt_on_error=1 history_size=7'" >> /etc/environment; \ echo "TSAN_SYMBOLIZER_PATH=/usr/lib/llvm-8/bin/llvm-symbolizer" >> /etc/environment; \ echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment; \ echo "ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \ diff --git a/docker/test/stateful_with_coverage/Dockerfile b/docker/test/stateful_with_coverage/Dockerfile new file mode 100644 index 00000000000..2a566bdcf01 --- /dev/null +++ b/docker/test/stateful_with_coverage/Dockerfile @@ -0,0 +1,19 @@ +# docker build -t yandex/clickhouse-stateful-test . +FROM yandex/clickhouse-stateless-test + +RUN echo "deb [trusted=yes] http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" >> /etc/apt/sources.list + +RUN apt-get update -y \ + && env DEBIAN_FRONTEND=noninteractive \ + apt-get install --yes --no-install-recommends \ + python-requests \ + llvm-8 \ + llvm-9 + +COPY s3downloader /s3downloader +COPY run.sh /run.sh + +ENV DATASETS="hits visits" + +CMD ["/bin/bash", "/run.sh"] + diff --git a/docker/test/stateful_with_coverage/run.sh b/docker/test/stateful_with_coverage/run.sh new file mode 100755 index 00000000000..6ec0bfa155a --- /dev/null +++ b/docker/test/stateful_with_coverage/run.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +kill_clickhouse () { + while kill -0 `pgrep -u clickhouse`; + do + kill `pgrep -u clickhouse` 2>/dev/null + echo "Process" `pgrep -u clickhouse` "still alive" + sleep 10 + done +} + +start_clickhouse () { + LLVM_PROFILE_FILE='server_%h_%p_%m.profraw' sudo -Eu clickhouse /usr/bin/clickhouse-server --config /etc/clickhouse-server/config.xml & +} + +wait_llvm_profdata () { + while kill -0 `pgrep llvm-profdata-9`; + do + echo "Waiting for profdata " `pgrep llvm-profdata-9` "still alive" + sleep 3 + done +} + +merge_client_files_in_background () { + client_files=`ls /client_*profraw 2>/dev/null` + if [ ! -z "$client_files" ] + then + llvm-profdata-9 merge -sparse $client_files -o merged_client_`date +%s`.profraw + rm $client_files + fi +} + +chmod 777 / + +dpkg -i package_folder/clickhouse-common-static_*.deb; \ + dpkg -i package_folder/clickhouse-common-static-dbg_*.deb; \ + dpkg -i package_folder/clickhouse-server_*.deb; \ + dpkg -i package_folder/clickhouse-client_*.deb; \ + dpkg -i package_folder/clickhouse-test_*.deb + +mkdir -p /var/lib/clickhouse +mkdir -p /var/log/clickhouse-server +chmod 777 -R /var/log/clickhouse-server/ + +ln -s /usr/share/clickhouse-test/config/zookeeper.xml /etc/clickhouse-server/config.d/; \ + ln -s /usr/share/clickhouse-test/config/listen.xml /etc/clickhouse-server/config.d/; \ + ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/; \ + ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/; \ + ln -s /usr/share/clickhouse-test/config/readonly.xml /etc/clickhouse-server/users.d/; \ + ln -s /usr/share/clickhouse-test/config/ints_dictionary.xml /etc/clickhouse-server/; \ + ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/; \ + ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/; \ + ln -s /usr/lib/llvm-8/bin/llvm-symbolizer /usr/bin/llvm-symbolizer + + +service zookeeper start + +sleep 5 + +start_clickhouse + +sleep 5 + +/s3downloader --dataset-names $DATASETS + +chmod 777 -R /var/lib/clickhouse + +while /bin/true; do + merge_client_files_in_background + sleep 2 +done & + +LLVM_PROFILE_FILE='client_%h_%p_%m.profraw' clickhouse-client --query "SHOW DATABASES" +LLVM_PROFILE_FILE='client_%h_%p_%m.profraw' clickhouse-client --query "CREATE DATABASE datasets" +LLVM_PROFILE_FILE='client_%h_%p_%m.profraw' clickhouse-client --query "CREATE DATABASE test" + +kill_clickhouse +start_clickhouse + +sleep 10 + +LLVM_PROFILE_FILE='client_%h_%p_%m.profraw' clickhouse-client --query "SHOW TABLES FROM datasets" +LLVM_PROFILE_FILE='client_%h_%p_%m.profraw' clickhouse-client --query "SHOW TABLES FROM test" +LLVM_PROFILE_FILE='client_%h_%p_%m.profraw' clickhouse-client --query "RENAME TABLE datasets.hits_v1 TO test.hits" +LLVM_PROFILE_FILE='client_%h_%p_%m.profraw' clickhouse-client --query "RENAME TABLE datasets.visits_v1 TO test.visits" +LLVM_PROFILE_FILE='client_%h_%p_%m.profraw' clickhouse-client --query "SHOW TABLES FROM test" +LLVM_PROFILE_FILE='client_%h_%p_%m.profraw' clickhouse-test --shard --zookeeper --no-stateless $SKIP_TESTS_OPTION 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee test_output/test_result.txt + +kill_clickhouse + +wait_llvm_profdata + +sleep 3 + +wait_llvm_profdata # 100% merged all parts + + +cp /*.profraw /profraw ||: diff --git a/docker/test/stateful_with_coverage/s3downloader b/docker/test/stateful_with_coverage/s3downloader new file mode 100755 index 00000000000..f8e2bf3cbe4 --- /dev/null +++ b/docker/test/stateful_with_coverage/s3downloader @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import os +import sys +import tarfile +import logging +import argparse +import requests +import tempfile + + +DEFAULT_URL = 'https://clickhouse-datasets.s3.yandex.net' + +AVAILABLE_DATASETS = { + 'hits': 'hits_v1.tar', + 'visits': 'visits_v1.tar', +} + +def _get_temp_file_name(): + return os.path.join(tempfile._get_default_tempdir(), next(tempfile._get_candidate_names())) + +def build_url(base_url, dataset): + return os.path.join(base_url, dataset, 'partitions', AVAILABLE_DATASETS[dataset]) + +def dowload_with_progress(url, path): + logging.info("Downloading from %s to temp path %s", url, path) + with open(path, 'w') as f: + response = requests.get(url, stream=True) + response.raise_for_status() + total_length = response.headers.get('content-length') + if total_length is None or int(total_length) == 0: + logging.info("No content-length, will download file without progress") + f.write(response.content) + else: + dl = 0 + total_length = int(total_length) + logging.info("Content length is %ld bytes", total_length) + for data in response.iter_content(chunk_size=4096): + dl += len(data) + f.write(data) + if sys.stdout.isatty(): + done = int(50 * dl / total_length) + percent = int(100 * float(dl) / total_length) + sys.stdout.write("\r[{}{}] {}%".format('=' * done, ' ' * (50-done), percent)) + sys.stdout.flush() + sys.stdout.write("\n") + logging.info("Downloading finished") + +def unpack_to_clickhouse_directory(tar_path, clickhouse_path): + logging.info("Will unpack data from temp path %s to clickhouse db %s", tar_path, clickhouse_path) + with tarfile.open(tar_path, 'r') as comp_file: + comp_file.extractall(path=clickhouse_path) + logging.info("Unpack finished") + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + + parser = argparse.ArgumentParser( + description="Simple tool for dowloading datasets for clickhouse from S3") + + parser.add_argument('--dataset-names', required=True, nargs='+', choices=AVAILABLE_DATASETS.keys()) + parser.add_argument('--url-prefix', default=DEFAULT_URL) + parser.add_argument('--clickhouse-data-path', default='/var/lib/clickhouse/') + + args = parser.parse_args() + datasets = args.dataset_names + logging.info("Will fetch following datasets: %s", ', '.join(datasets)) + for dataset in datasets: + logging.info("Processing %s", dataset) + temp_archive_path = _get_temp_file_name() + try: + download_url_for_dataset = build_url(args.url_prefix, dataset) + dowload_with_progress(download_url_for_dataset, temp_archive_path) + unpack_to_clickhouse_directory(temp_archive_path, args.clickhouse_data_path) + except Exception as ex: + logging.info("Some exception occured %s", str(ex)) + raise + finally: + logging.info("Will remove dowloaded file %s from filesystem if it exists", temp_archive_path) + if os.path.exists(temp_archive_path): + os.remove(temp_archive_path) + logging.info("Processing of %s finished", dataset) + logging.info("Fetch finished, enjoy your tables!") + + diff --git a/docker/test/stateless/Dockerfile b/docker/test/stateless/Dockerfile index 16f8fc437bc..4e1a20d848b 100644 --- a/docker/test/stateless/Dockerfile +++ b/docker/test/stateless/Dockerfile @@ -45,7 +45,7 @@ CMD dpkg -i package_folder/clickhouse-common-static_*.deb; \ ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/; \ ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/; \ ln -s /usr/lib/llvm-8/bin/llvm-symbolizer /usr/bin/llvm-symbolizer; \ - echo "TSAN_OPTIONS='halt_on_error=1 history_size=7'" >> /etc/environment; \ + echo "TSAN_OPTIONS='verbosity=1000 halt_on_error=1 history_size=7'" >> /etc/environment; \ echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment; \ echo "ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \ echo "UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \ diff --git a/docker/test/stateless_with_coverage/Dockerfile b/docker/test/stateless_with_coverage/Dockerfile new file mode 100644 index 00000000000..b9da18223ab --- /dev/null +++ b/docker/test/stateless_with_coverage/Dockerfile @@ -0,0 +1,36 @@ +# docker build -t yandex/clickhouse-stateless-with-coverage-test . +FROM yandex/clickhouse-deb-builder + +RUN echo "deb [trusted=yes] http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" >> /etc/apt/sources.list + +RUN apt-get update -y \ + && env DEBIAN_FRONTEND=noninteractive \ + apt-get install --yes --no-install-recommends \ + bash \ + tzdata \ + fakeroot \ + debhelper \ + zookeeper \ + zookeeperd \ + expect \ + python \ + python-lxml \ + python-termcolor \ + python-requests \ + curl \ + sudo \ + openssl \ + netcat-openbsd \ + telnet \ + moreutils \ + brotli \ + gdb \ + lsof \ + llvm-9 + + +ENV TZ=Europe/Moscow +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone +COPY run.sh /run.sh + +CMD ["/bin/bash", "/run.sh"] diff --git a/docker/test/stateless_with_coverage/run.sh b/docker/test/stateless_with_coverage/run.sh new file mode 100755 index 00000000000..50082337757 --- /dev/null +++ b/docker/test/stateless_with_coverage/run.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +kill_clickhouse () { + while kill -0 `pgrep -u clickhouse`; + do + kill `pgrep -u clickhouse` 2>/dev/null + echo "Process" `pgrep -u clickhouse` "still alive" + sleep 10 + done +} + +wait_llvm_profdata () { + while kill -0 `pgrep llvm-profdata-9`; + do + echo "Waiting for profdata " `pgrep llvm-profdata-9` "still alive" + sleep 3 + done +} + +start_clickhouse () { + LLVM_PROFILE_FILE='server_%h_%p_%m.profraw' sudo -Eu clickhouse /usr/bin/clickhouse-server --config /etc/clickhouse-server/config.xml & +} + +merge_client_files_in_background () { + client_files=`ls /client_*profraw 2>/dev/null` + if [ ! -z "$client_files" ] + then + llvm-profdata-9 merge -sparse $client_files -o merged_client_`date +%s`.profraw + rm $client_files + fi +} + +chmod 777 / + +dpkg -i package_folder/clickhouse-common-static_*.deb; \ + dpkg -i package_folder/clickhouse-common-static-dbg_*.deb; \ + dpkg -i package_folder/clickhouse-server_*.deb; \ + dpkg -i package_folder/clickhouse-client_*.deb; \ + dpkg -i package_folder/clickhouse-test_*.deb + + +mkdir -p /var/lib/clickhouse +mkdir -p /var/log/clickhouse-server +chmod 777 -R /var/lib/clickhouse +chmod 777 -R /var/log/clickhouse-server/ + +ln -s /usr/share/clickhouse-test/config/zookeeper.xml /etc/clickhouse-server/config.d/; \ + ln -s /usr/share/clickhouse-test/config/listen.xml /etc/clickhouse-server/config.d/; \ + ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/; \ + ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/; \ + ln -s /usr/share/clickhouse-test/config/readonly.xml /etc/clickhouse-server/users.d/; \ + ln -s /usr/share/clickhouse-test/config/ints_dictionary.xml /etc/clickhouse-server/; \ + ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/; \ + ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/; \ + ln -s /usr/lib/llvm-8/bin/llvm-symbolizer /usr/bin/llvm-symbolizer + +service zookeeper start +sleep 5 + +start_clickhouse + +sleep 10 + +while /bin/true; do + merge_client_files_in_background + sleep 2 +done & + +LLVM_PROFILE_FILE='client_%h_%p_%m.profraw' clickhouse-test --shard --zookeeper $ADDITIONAL_OPTIONS $SKIP_TESTS_OPTION 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee test_output/test_result.txt + +kill_clickhouse + +wait_llvm_profdata + +sleep 3 + +wait_llvm_profdata # 100% merged all parts + +cp /*.profraw /profraw ||: diff --git a/docker/test/stress/Dockerfile b/docker/test/stress/Dockerfile index 0ee49d64d51..b0b94ccc579 100644 --- a/docker/test/stress/Dockerfile +++ b/docker/test/stress/Dockerfile @@ -34,13 +34,8 @@ CMD dpkg -i package_folder/clickhouse-common-static_*.deb; \ ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/; \ ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/; \ ln -s /usr/lib/llvm-8/bin/llvm-symbolizer /usr/bin/llvm-symbolizer; \ - echo "TSAN_OPTIONS='halt_on_error=1 history_size=7'" >> /etc/environment; \ - echo "TSAN_SYMBOLIZER_PATH=/usr/lib/llvm-8/bin/llvm-symbolizer" >> /etc/environment; \ + echo "TSAN_OPTIONS='halt_on_error=1 history_size=7 ignore_noninstrumented_modules=1 verbosity=1'" >> /etc/environment; \ echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment; \ - echo "ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \ - echo "UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \ - echo "TSAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \ - echo "LLVM_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer" >> /etc/environment; \ service clickhouse-server start && sleep 5 \ && /s3downloader --dataset-names $DATASETS \ && chmod 777 -R /var/lib/clickhouse \ diff --git a/docs/en/database_engines/index.md b/docs/en/database_engines/index.md new file mode 100644 index 00000000000..3190a79017f --- /dev/null +++ b/docs/en/database_engines/index.md @@ -0,0 +1,9 @@ +# Database Engines + +Database engines provide working with tables. + +By default, ClickHouse uses its native database engine which provides configurable [table engines](../operations/table_engines/index.md) and [SQL dialect](../query_language/syntax.md). + +Also you can use the following database engines: + +- [MySQL](mysql.md) diff --git a/docs/en/database_engines/mysql.md b/docs/en/database_engines/mysql.md new file mode 100644 index 00000000000..fd5417ee27d --- /dev/null +++ b/docs/en/database_engines/mysql.md @@ -0,0 +1,122 @@ +# MySQL + +Allows to connect to some database on remote MySQL server and perform `INSERT` and `SELECT` queries with tables to exchange data between ClickHouse and MySQL. + +The `MySQL` database engine translate queries to the MySQL server, so you can perform operations such as `SHOW TABLES` or `SHOW CREATE TABLE`. + +You cannot perform with tables the following queries: + +- `ATTACH`/`DETACH` +- `DROP` +- `RENAME` +- `CREATE TABLE` +- `ALTER` + + +## Creating a Database + +``` sql +CREATE DATABASE [IF NOT EXISTS] db_name [ON CLUSTER cluster] +ENGINE = MySQL('host:port', 'database', 'user', 'password') +``` + +**Engine Parameters** + +- `host:port` — MySQL server address. +- `database` — Remote database name. +- `user` — MySQL user. +- `password` — User password. + + +## Data Types Support + +MySQL | ClickHouse +------|------------ +UNSIGNED TINYINT | [UInt8](../data_types/int_uint.md) +TINYINT | [Int8](../data_types/int_uint.md) +UNSIGNED SMALLINT | [UInt16](../data_types/int_uint.md) +SMALLINT | [Int16](../data_types/int_uint.md) +UNSIGNED INT, UNSIGNED MEDIUMINT | [UInt32](../data_types/int_uint.md) +INT, MEDIUMINT | [Int32](../data_types/int_uint.md) +UNSIGNED BIGINT | [UInt64](../data_types/int_uint.md) +BIGINT | [Int64](../data_types/int_uint.md) +FLOAT | [Float32](../data_types/float.md) +DOUBLE | [Float64](../data_types/float.md) +DATE | [Date](../data_types/date.md) +DATETIME, TIMESTAMP | [DateTime](../data_types/datetime.md) +BINARY | [FixedString](../data_types/fixedstring.md) + +All other MySQL data types are converted into [String](../data_types/string.md). + +[Nullable](../data_types/nullable.md) data type is supported. + + +## Examples of Use + +Table in MySQL: + +``` +mysql> USE test; +Database changed + +mysql> CREATE TABLE `mysql_table` ( + -> `int_id` INT NOT NULL AUTO_INCREMENT, + -> `float` FLOAT NOT NULL, + -> PRIMARY KEY (`int_id`)); +Query OK, 0 rows affected (0,09 sec) + +mysql> insert into mysql_table (`int_id`, `float`) VALUES (1,2); +Query OK, 1 row affected (0,00 sec) + +mysql> select * from mysql_table; ++--------+-------+ +| int_id | value | ++--------+-------+ +| 1 | 2 | ++--------+-------+ +1 row in set (0,00 sec) +``` + +Database in ClickHouse, exchanging data with the MySQL server: + +```sql +CREATE DATABASE mysql_db ENGINE = MySQL('localhost:3306', 'test', 'my_user', 'user_password') +``` +```sql +SHOW DATABASES +``` +```text +┌─name─────┐ +│ default │ +│ mysql_db │ +│ system │ +└──────────┘ +``` +```sql +SHOW TABLES FROM mysql_db +``` +```text +┌─name─────────┐ +│ mysql_table │ +└──────────────┘ +``` +```sql +SELECT * FROM mysql_db.mysql_table +``` +```text +┌─int_id─┬─value─┐ +│ 1 │ 2 │ +└────────┴───────┘ +``` +```sql +INSERT INTO mysql_db.mysql_table VALUES (3,4) +``` +```sql +SELECT * FROM mysql_db.mysql_table +``` +```text +┌─int_id─┬─value─┐ +│ 1 │ 2 │ +│ 3 │ 4 │ +└────────┴───────┘ +``` diff --git a/docs/en/interfaces/formats.md b/docs/en/interfaces/formats.md index 29055aac09e..7d5add49bb4 100644 --- a/docs/en/interfaces/formats.md +++ b/docs/en/interfaces/formats.md @@ -1,10 +1,14 @@ # Formats for input and output data {#formats} -ClickHouse can accept (`INSERT`) and return (`SELECT`) data in various formats. +ClickHouse can accept and return data in various formats. A format supported +for input can be used to parse the data provided to `INSERT`s, to perform +`SELECT`s from a file-backed table such as File, URL or HDFS, or to read an +external dictionary. A format supported for output can be used to arrange the +results of a `SELECT`, and to perform `INSERT`s into a file-backed table. -The table below lists supported formats and how they can be used in `INSERT` and `SELECT` queries. +The supported formats are: -| Format | INSERT | SELECT | +| Format | Input | Output | | ------- | -------- | -------- | | [TabSeparated](#tabseparated) | ✔ | ✔ | | [TabSeparatedRaw](#tabseparatedraw) | ✗ | ✔ | @@ -165,8 +169,7 @@ clickhouse-client --format_csv_delimiter="|" --query="INSERT INTO test.csv FORMA When parsing, all values can be parsed either with or without quotes. Both double and single quotes are supported. Rows can also be arranged without quotes. In this case, they are parsed up to the delimiter character or line feed (CR or LF). In violation of the RFC, when parsing rows without quotes, the leading and trailing spaces and tabs are ignored. For the line feed, Unix (LF), Windows (CR LF) and Mac OS Classic (CR LF) types are all supported. -Empty unquoted input values are replaced with default values for the respective -columns, if +Empty unquoted input values are replaced with default values for the respective columns, if [input_format_defaults_for_omitted_fields](../operations/settings/settings.md#session_settings-input_format_defaults_for_omitted_fields) is enabled. diff --git a/docs/en/operations/settings/settings.md b/docs/en/operations/settings/settings.md index b7b12e31c06..5d299e72bdf 100644 --- a/docs/en/operations/settings/settings.md +++ b/docs/en/operations/settings/settings.md @@ -199,15 +199,10 @@ Ok. ## input_format_defaults_for_omitted_fields {#session_settings-input_format_defaults_for_omitted_fields} -When performing `INSERT` queries, replace omitted input column values with -default values of the respective columns. This option only applies to -[JSONEachRow](../../interfaces/formats.md#jsoneachrow) and -[CSV](../../interfaces/formats.md#csv) formats. +When performing `INSERT` queries, replace omitted input column values with default values of the respective columns. This option only applies to [JSONEachRow](../../interfaces/formats.md#jsoneachrow) and [CSV](../../interfaces/formats.md#csv) formats. !!! note "Note" - When this option is enabled, extended table metadata are sent -from server to client. It consumes additional computing resources on the server -and can reduce performance. + When this option is enabled, extended table metadata are sent from server to client. It consumes additional computing resources on the server and can reduce performance. Possible values: diff --git a/docs/en/operations/settings/settings_users.md b/docs/en/operations/settings/settings_users.md index 1b8cb640a9a..7f5dba73306 100644 --- a/docs/en/operations/settings/settings_users.md +++ b/docs/en/operations/settings/settings_users.md @@ -1,6 +1,6 @@ # User settings -The `users` section of the `user.xml` configuration file contains settings for users. +The `users` section of the `user.xml` configuration file contains user settings. Structure of the `users` section: @@ -35,15 +35,15 @@ Structure of the `users` section: Password could be specified in plaintext or in SHA256 (hex format). -- To specify password in plaintext (**not recommended**), place it in a `password` element. +- To assign a password in plaintext (**not recommended**), place it in a `password` element. - For example, `qwerty`. Password can be empty. + For example, `qwerty`. The password can be left blank. -- To specify SHA256 hash of a password, place it in a `password_sha256_hex` element. +- To assign a password using its SHA256 hash, place it in a `password_sha256_hex` element. For example, `65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5`. - Example of how to generate password from shell: + Example of how to generate a password from shell: ``` PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha256sum | tr -d '-' @@ -54,11 +54,11 @@ Password could be specified in plaintext or in SHA256 (hex format). ### user_name/networks -List of networks which the user can connect to ClickHouse server from. +List of networks from which the user can connect to the ClickHouse server. -Each element of list has one of the following forms: +Each element of the list can have one of the following forms: -- `` — IP-address or a network mask. +- `` — IP address or network mask. Examples: `213.180.204.3`, `10.0.0.1/8`, `10.0.0.1/255.255.255.0`, `2a02:6b8::3`, `2a02:6b8::3/64`, `2a02:6b8::3/ffff:ffff:ffff:ffff::`. @@ -66,15 +66,15 @@ Each element of list has one of the following forms: Example: `server01.yandex.ru`. - To check access, DNS query is performed, and all returned IP-addresses are compared to peer address. + To check access, a DNS query is performed, and all returned IP addresses are compared to the peer address. - `` — Regular expression for hostnames. Example, `^server\d\d-\d\d-\d\.yandex\.ru$` - To check access, [DNS PTR query](https://en.wikipedia.org/wiki/Reverse_DNS_lookup) is performed for peer address and then regexp is applied. Then, for result of PTR query, another DNS query is performed and all received addresses compared to peer address. Strongly recommended that regexp is ends with $ + To check access, a [DNS PTR query](https://en.wikipedia.org/wiki/Reverse_DNS_lookup) is performed for the peer address and then the specified regexp is applied. Then, another DNS query is performed for the results of the PTR query and all the received addresses are compared to the peer address. We strongly recommend that regexp ends with $. -All results of DNS requests are cached till server restart. +All results of DNS requests are cached until the server restarts. **Examples** @@ -85,7 +85,7 @@ To open access for user from any network, specify: ``` !!! warning "Warning" - It's insecure to open access from any network, unless you have a firewall properly configured or server is not directly connected to Internet. + It's insecure to open access from any network unless you have a firewall properly configured or the server is not directly connected to Internet. To open access only from localhost, specify: @@ -97,22 +97,22 @@ To open access only from localhost, specify: ### user_name/profile -You can assign a settings profile for the user. Settings profiles are configured in a separate section of the `users.xml` file. For more information see the [Profiles of Settings](settings_profiles.md). +You can assign a settings profile for the user. Settings profiles are configured in a separate section of the `users.xml` file. For more information, see [Profiles of Settings](settings_profiles.md). ### user_name/quota -Quotas allow you to limit resource usage over a period of time, or track the use of resources. Quotas are configured in the `quotas` +Quotas allow you to track or limit resource usage over a period of time. Quotas are configured in the `quotas` section of the `users.xml` configuration file. -You can assign a quotas set for the user. For the detailed description of quotas configuration see the [Quotas](../quotas.md#quotas) section. +You can assign a quotas set for the user. For a detailed description of quotas configuration, see [Quotas](../quotas.md#quotas). ### user_name/databases -In this section you can you can limit rows that are returned by ClickHouse for `SELECT` queries of current user, thus implementing basic row level security. +In this section, you can you can limit rows that are returned by ClickHouse for `SELECT` queries made by the current user, thus implementing basic row-level security. **Example** -The following configuration sets that the user `user1` can see only the rows of `table1` as a result of `SELECT` query where the value of field `id` equals to 1000. +The following configuration forces that user `user1` can only see the rows of `table1` as the result of `SELECT` queries, where the value of the `id` field is 1000. ``` @@ -126,4 +126,6 @@ The following configuration sets that the user `user1` can see only the rows of ``` -The `filter` can be any expression resulting with the [UInt8](../../data_types/int_uint.md)-typed value. It usually contains comparisons and logical operators. Rows from `database_name.table1` where filter results to 0 are not returned for this user. The filtering is incompatible with `PREWHERE` operations and disables `WHERE→PREWHERE` optimization. +The `filter` can be any expression resulting in a [UInt8](../../data_types/int_uint.md)-type value. It usually contains comparisons and logical operators. Rows from `database_name.table1` where filter results to 0 are not returned for this user. The filtering is incompatible with `PREWHERE` operations and disables `WHERE→PREWHERE` optimization. + +[Original article](https://clickhouse.yandex/docs/en/operations/settings/settings_users/) diff --git a/docs/en/operations/table_engines/collapsingmergetree.md b/docs/en/operations/table_engines/collapsingmergetree.md index cf521ac4cd1..b4f7bd8e6cf 100644 --- a/docs/en/operations/table_engines/collapsingmergetree.md +++ b/docs/en/operations/table_engines/collapsingmergetree.md @@ -2,7 +2,7 @@ The engine inherits from [MergeTree](mergetree.md) and adds the logic of rows collapsing to data parts merge algorithm. -`CollapsingMergeTree` asynchronously deletes (collapses) pairs of rows if all of the fields in a row are equivalent excepting the particular field `Sign` which can have `1` and `-1` values. Rows without a pair are kept. For more details see the [Collapsing](#table_engine-collapsingmergetree-collapsing) section of the document. +`CollapsingMergeTree` asynchronously deletes (collapses) pairs of rows if all of the fields in a sorting key (`ORDER BY`) are equivalent excepting the particular field `Sign` which can have `1` and `-1` values. Rows without a pair are kept. For more details see the [Collapsing](#table_engine-collapsingmergetree-collapsing) section of the document. The engine may significantly reduce the volume of storage and increase efficiency of `SELECT` query as a consequence. @@ -80,7 +80,7 @@ At some moment later we register the change of user activity and write it with t └─────────────────────┴───────────┴──────────┴──────┘ ``` -The first row cancels the previous state of the object (user). It should copy all of the fields of the canceled state excepting `Sign`. +The first row cancels the previous state of the object (user). It should copy the sorting key fields of the canceled state excepting `Sign`. The second row contains the current state. @@ -99,13 +99,13 @@ Why we need 2 rows for each change read in the [Algorithm](#table_engine-collaps **Peculiar properties of such approach** -1. The program that writes the data should remember the state of an object to be able to cancel it. "Cancel" string should be the copy of "state" string with the opposite `Sign`. It increases the initial size of storage but allows to write the data quickly. +1. The program that writes the data should remember the state of an object to be able to cancel it. "Cancel" string should contain copies of the sorting key fields of the "state" string and the opposite `Sign`. It increases the initial size of storage but allows to write the data quickly. 2. Long growing arrays in columns reduce the efficiency of the engine due to load for writing. The more straightforward data, the higher efficiency. 3. The `SELECT` results depend strongly on the consistency of object changes history. Be accurate when preparing data for inserting. You can get unpredictable results in inconsistent data, for example, negative values for non-negative metrics such as session depth. ### Algorithm {#table_engine-collapsingmergetree-collapsing-algorithm} -When ClickHouse merges data parts, each group of consecutive rows with the same primary key is reduced to not more than two rows, one with `Sign = 1` ("state" row) and another with `Sign = -1` ("cancel" row). In other words, entries collapse. +When ClickHouse merges data parts, each group of consecutive rows with the same sorting key (`ORDER BY`) is reduced to not more than two rows, one with `Sign = 1` ("state" row) and another with `Sign = -1` ("cancel" row). In other words, entries collapse. For each resulting data part ClickHouse saves: @@ -119,9 +119,9 @@ For each resulting data part ClickHouse saves: Thus, collapsing should not change the results of calculating statistics. Changes gradually collapsed so that in the end only the last state of almost every object left. -The `Sign` is required because the merging algorithm doesn't guarantee that all of the rows with the same primary key will be in the same resulting data part and even on the same physical server. ClickHouse process `SELECT` queries with multiple threads, and it can not predict the order of rows in the result. The aggregation is required if there is a need to get completely "collapsed" data from `CollapsingMergeTree` table. +The `Sign` is required because the merging algorithm doesn't guarantee that all of the rows with the same sorting key will be in the same resulting data part and even on the same physical server. ClickHouse process `SELECT` queries with multiple threads, and it can not predict the order of rows in the result. The aggregation is required if there is a need to get completely "collapsed" data from `CollapsingMergeTree` table. -To finalize collapsing write a query with `GROUP BY` clause and aggregate functions that account for the sign. For example, to calculate quantity, use `sum(Sign)` instead of `count()`. To calculate the sum of something, use `sum(Sign * x)` instead of `sum(x)`, and so on, and also add `HAVING sum(Sign) > 0`. +To finalize collapsing, write a query with `GROUP BY` clause and aggregate functions that account for the sign. For example, to calculate quantity, use `sum(Sign)` instead of `count()`. To calculate the sum of something, use `sum(Sign * x)` instead of `sum(x)`, and so on, and also add `HAVING sum(Sign) > 0`. The aggregates `count`, `sum` and `avg` could be calculated this way. The aggregate `uniq` could be calculated if an object has at least one state not collapsed. The aggregates `min` and `max` could not be calculated because `CollapsingMergeTree` does not save values history of the collapsed states. diff --git a/docs/en/operations/table_engines/file.md b/docs/en/operations/table_engines/file.md index 284f8deff58..82c536646ac 100644 --- a/docs/en/operations/table_engines/file.md +++ b/docs/en/operations/table_engines/file.md @@ -1,6 +1,7 @@ -# File(InputFormat) {#table_engines-file} +# File {#table_engines-file} -The data source is a file that stores data in one of the supported input formats (TabSeparated, Native, etc.). +The File table engine keeps the data in a file in one of the supported [file +formats](../../interfaces/formats.md#formats) (TabSeparated, Native, etc.). Usage examples: @@ -14,7 +15,10 @@ Usage examples: File(Format) ``` -`Format` should be supported for either `INSERT` and `SELECT`. For the full list of supported formats see [Formats](../../interfaces/formats.md#formats). +The `Format` parameter specifies one of the available file formats. To perform +`SELECT` queries, the format must be supported for input, and to perform +`INSERT` queries -- for output. The available formats are listed in the +[Formats](../../interfaces/formats.md#formats) section. ClickHouse does not allow to specify filesystem path for`File`. It will use folder defined by [path](../server_settings/settings.md) setting in server configuration. diff --git a/docs/en/operations/table_engines/kafka.md b/docs/en/operations/table_engines/kafka.md index 22d0384fd42..7bedd8f7ac9 100644 --- a/docs/en/operations/table_engines/kafka.md +++ b/docs/en/operations/table_engines/kafka.md @@ -26,7 +26,7 @@ SETTINGS [kafka_row_delimiter = 'delimiter_symbol',] [kafka_schema = '',] [kafka_num_consumers = N,] - [kafka_skip_broken_messages = <0|1>] + [kafka_skip_broken_messages = N] ``` Required parameters: @@ -40,7 +40,7 @@ Optional parameters: - `kafka_row_delimiter` – Delimiter character, which ends the message. - `kafka_schema` – Parameter that must be used if the format requires a schema definition. For example, [Cap'n Proto](https://capnproto.org/) requires the path to the schema file and the name of the root `schema.capnp:Message` object. - `kafka_num_consumers` – The number of consumers per table. Default: `1`. Specify more consumers if the throughput of one consumer is insufficient. The total number of consumers should not exceed the number of partitions in the topic, since only one consumer can be assigned per partition. -- `kafka_skip_broken_messages` – Kafka message parser mode. If `kafka_skip_broken_messages = 1` then the engine skips the Kafka messages that can't be parsed (a message equals a row of data). +- `kafka_skip_broken_messages` – Kafka message parser tolerance to schema-incompatible messages per block. Default: `0`. If `kafka_skip_broken_messages = N` then the engine skips *N* Kafka messages that cannot be parsed (a message equals a row of data). Examples: @@ -100,6 +100,7 @@ Groups are flexible and synced on the cluster. For instance, if you have 10 topi 3. Create a materialized view that converts data from the engine and puts it into a previously created table. When the `MATERIALIZED VIEW` joins the engine, it starts collecting data in the background. This allows you to continually receive messages from Kafka and convert them to the required format using `SELECT`. +One kafka table can have as many materialized views as you like, they do not read data from the kafka table directly, but receive new records (in blocks), this way you can write to several tables with different detail level (with grouping - aggregation and without). Example: diff --git a/docs/en/operations/table_engines/merge.md b/docs/en/operations/table_engines/merge.md index 366a5459bf8..f29075ec973 100644 --- a/docs/en/operations/table_engines/merge.md +++ b/docs/en/operations/table_engines/merge.md @@ -27,11 +27,11 @@ Example 2: Let's say you have a old table (WatchLog_old) and decided to change partitioning without moving data to a new table (WatchLog_new) and you need to see data from both tables. ``` -CREATE TABLE WatchLog_old(date Date, UserId Int64, EventType String, Cnt UInt64) +CREATE TABLE WatchLog_old(date Date, UserId Int64, EventType String, Cnt UInt64) ENGINE=MergeTree(date, (UserId, EventType), 8192); INSERT INTO WatchLog_old VALUES ('2018-01-01', 1, 'hit', 3); -CREATE TABLE WatchLog_new(date Date, UserId Int64, EventType String, Cnt UInt64) +CREATE TABLE WatchLog_new(date Date, UserId Int64, EventType String, Cnt UInt64) ENGINE=MergeTree PARTITION BY date ORDER BY (UserId, EventType) SETTINGS index_granularity=8192; INSERT INTO WatchLog_new VALUES ('2018-01-02', 2, 'hit', 3); @@ -61,7 +61,9 @@ Virtual columns differ from normal columns in the following ways: - They are not selected when using the asterisk (`SELECT *`). - Virtual columns are not shown in `SHOW CREATE TABLE` and `DESC TABLE` queries. -The `Merge` type table contains a virtual `_table` column of the `String` type. (If the table already has a `_table` column, the virtual column is called `_table1`; if you already have `_table1`, it's called `_table2`, and so on.) It contains the name of the table that data was read from. +The `Merge` type table contains the virtual column `_table` of the type `String`. It contains the name of the table that data was read from. If any underlying table already has the column `_table`, then the virtual column is shadowed and is not accessible. + + If the `WHERE/PREWHERE` clause contains conditions for the `_table` column that do not depend on other table columns (as one of the conjunction elements, or as an entire expression), these conditions are used as an index. The conditions are performed on a data set of table names to read data from, and the read operation will be performed from only those tables that the condition was triggered on. diff --git a/docs/en/operations/table_engines/mergetree.md b/docs/en/operations/table_engines/mergetree.md index 86734031f3f..523b442319a 100644 --- a/docs/en/operations/table_engines/mergetree.md +++ b/docs/en/operations/table_engines/mergetree.md @@ -78,6 +78,7 @@ For a description of request parameters, see [request description](../../query_l - `index_granularity` — The granularity of an index. The number of data rows between the "marks" of an index. By default, 8192. The list of all available parameters you can see in [MergeTreeSettings.h](https://github.com/yandex/ClickHouse/blob/master/dbms/src/Storages/MergeTree/MergeTreeSettings.h). - `use_minimalistic_part_header_in_zookeeper` — Storage method of the data parts headers in ZooKeeper. If `use_minimalistic_part_header_in_zookeeper=1`, then ZooKeeper stores less data. For more information refer the [setting description](../server_settings/settings.md#server-settings-use_minimalistic_part_header_in_zookeeper) in the "Server configuration parameters" chapter. - `min_merge_bytes_to_use_direct_io` — The minimum data volume for merge operation required for using of the direct I/O access to the storage disk. During the merging of the data parts, ClickHouse calculates summary storage volume of all the data to be merged. If the volume exceeds `min_merge_bytes_to_use_direct_io` bytes, then ClickHouse reads and writes the data using direct I/O interface (`O_DIRECT` option) to the storage disk. If `min_merge_bytes_to_use_direct_io = 0`, then the direct I/O is disabled. Default value: `10 * 1024 * 1024 * 1024` bytes. +
- `merge_with_ttl_timeout` — Minimal time in seconds, when merge with TTL can be repeated. Default value: 86400 (1 day). **Example of sections setting** @@ -315,12 +316,42 @@ For concurrent table access, we use multi-versioning. In other words, when a tab Reading from a table is automatically parallelized. -## TTL for columns and tables +## TTL for columns and tables {#table_engine-mergetree-ttl} -Data with expired TTL is removed while executing merges. +Determines the lifetime of values. -If TTL is set for column, when it expires, value will be replaced by default. If all values in columns were zeroed in part, data for this column will be deleted from disk for part. You are not allowed to set TTL for all key columns. If TTL is set for table, when it expires, row will be deleted. +The `TTL` clause can be set for the whole table and for each individual column. If `TTL` is set for the whole table, individual `TTL` for columns are ignored. -When TTL expires on some value or row in part, extra merge will be executed. To control frequency of merges with TTL you can set `merge_with_ttl_timeout`. If it is too low, many extra merges and lack of regular merges can reduce the perfomance. + +The table must have the column of the [Date](../../data_types/date.md) or [DateTime](../../data_types/datetime.md) data type. This date column should be used in the `TTL` clause. You can only set lifetime of the data as an interval from the date column value. + +``` +TTL date_time + interval +``` + +You can set the `interval` by any expression, returning the value of the `DateTime` data type. For example, you can use [time interval](../../query_language/operators.md#operators-datetime) operators. + +``` +TTL date_time + INTERVAL 1 MONTH +TTL date_time + INTERVAL 15 HOUR +``` + +**Column TTL** + +When the values in the column expire, ClickHouse replace them with the default values for the column data type. If all the column values in the data part become expired, ClickHouse deletes this column from the data part in a filesystem. + +The `TTL` clause cannot be used for key columns. + +**Table TTL** + +When some data in table expires, ClickHouse deletes all the corresponding rows. + +**Cleaning up of Data** + +Data with expired TTL is removed, when ClickHouse merges data parts. + +When ClickHouse see that some data is expired, it performs off-schedule merge. To control frequency of such merges, you can set [merge_with_ttl_timeout](#mergetree_setting-merge_with_ttl_timeout). If it is too low, many off-schedule merges consume much resources. + +If you perform the `SELECT` query between merges you can get the expired data. To avoid it, use the [OPTIMIZE](../../query_language/misc.md#misc_operations-optimize) query before `SELECT`. [Original article](https://clickhouse.yandex/docs/en/operations/table_engines/mergetree/) diff --git a/docs/en/query_language/agg_functions/reference.md b/docs/en/query_language/agg_functions/reference.md index 87254fad58c..76fb90d4fc4 100644 --- a/docs/en/query_language/agg_functions/reference.md +++ b/docs/en/query_language/agg_functions/reference.md @@ -258,7 +258,7 @@ Value of the `UInt64` type. Test data: ``` -userid +UserID 1 1 2 @@ -268,7 +268,7 @@ userid Query: ``` -SELECT groupBitmap(userid) as num FROM t +SELECT groupBitmap(UserID) as num FROM t ``` Result: @@ -360,7 +360,7 @@ GROUP BY timeslot ## skewPop -Computes the [skewness](https://en.wikipedia.org/wiki/Skewness) for sequence. +Computes the [skewness](https://en.wikipedia.org/wiki/Skewness) of a sequence. ``` skewPop(expr) @@ -372,9 +372,9 @@ skewPop(expr) **Returned value** -The skewness of given distribution. Type — [Float64](../../data_types/float.md) +The skewness of the given distribution. Type — [Float64](../../data_types/float.md) -**Example of Use** +**Example** ```sql SELECT skewPop(value) FROM series_with_value_column @@ -382,9 +382,9 @@ SELECT skewPop(value) FROM series_with_value_column ## skewSamp -Computes the [sample skewness](https://en.wikipedia.org/wiki/Skewness) for sequence. +Computes the [sample skewness](https://en.wikipedia.org/wiki/Skewness) of a sequence. -It represents an unbiased estimate of the skewness of a random variable, if passed values form it's sample. +It represents an unbiased estimate of the skewness of a random variable if passed values form its sample. ``` skewSamp(expr) @@ -396,9 +396,9 @@ skewSamp(expr) **Returned value** -The skewness of given distribution. Type — [Float64](../../data_types/float.md). If `n <= 1` (`n` is a size of the sample), then the function returns `nan`. +The skewness of the given distribution. Type — [Float64](../../data_types/float.md). If `n <= 1` (`n` is the size of the sample), then the function returns `nan`. -**Example of Use** +**Example** ```sql SELECT skewSamp(value) FROM series_with_value_column @@ -406,7 +406,7 @@ SELECT skewSamp(value) FROM series_with_value_column ## kurtPop -Computes the [kurtosis](https://en.wikipedia.org/wiki/Kurtosis) for sequence. +Computes the [kurtosis](https://en.wikipedia.org/wiki/Kurtosis) of a sequence. ``` kurtPop(expr) @@ -418,9 +418,9 @@ kurtPop(expr) **Returned value** -The kurtosis of given distribution. Type — [Float64](../../data_types/float.md) +The kurtosis of the given distribution. Type — [Float64](../../data_types/float.md) -**Example of Use** +**Example** ```sql SELECT kurtPop(value) FROM series_with_value_column @@ -428,9 +428,9 @@ SELECT kurtPop(value) FROM series_with_value_column ## kurtSamp -Computes the [sample kurtosis](https://en.wikipedia.org/wiki/Kurtosis) for sequence. +Computes the [sample kurtosis](https://en.wikipedia.org/wiki/Kurtosis) of a sequence. -It represents an unbiased estimate of the kurtosis of a random variable, if passed values form it's sample. +It represents an unbiased estimate of the kurtosis of a random variable if passed values form its sample. ``` kurtSamp(expr) @@ -442,9 +442,9 @@ kurtSamp(expr) **Returned value** -The kurtosis of given distribution. Type — [Float64](../../data_types/float.md). If `n <= 1` (`n` is a size of the sample), then the function returns `nan`. +The kurtosis of the given distribution. Type — [Float64](../../data_types/float.md). If `n <= 1` (`n` is a size of the sample), then the function returns `nan`. -**Example of Use** +**Example** ```sql SELECT kurtSamp(value) FROM series_with_value_column @@ -763,7 +763,7 @@ All the quantile functions also have corresponding quantiles functions: `quantil Calculates the amount `Σ((x - x̅)^2) / (n - 1)`, where `n` is the sample size and `x̅`is the average value of `x`. -It represents an unbiased estimate of the variance of a random variable, if passed values form it's sample. +It represents an unbiased estimate of the variance of a random variable if passed values form its sample. Returns `Float64`. When `n <= 1`, returns `+∞`. diff --git a/docs/en/query_language/create.md b/docs/en/query_language/create.md index 926ba95173f..a6ae57bc00f 100644 --- a/docs/en/query_language/create.md +++ b/docs/en/query_language/create.md @@ -1,14 +1,31 @@ -## CREATE DATABASE +## CREATE DATABASE {#query_language-create-database} -Creating db_name databases +Creates database. ``` sql -CREATE DATABASE [IF NOT EXISTS] db_name [ON CLUSTER cluster] +CREATE DATABASE [IF NOT EXISTS] db_name [ON CLUSTER cluster] [ENGINE = engine(...)] ``` -`A database` is just a directory for tables. -If `IF NOT EXISTS` is included, the query won't return an error if the database already exists. +### Clauses +- `IF NOT EXISTS` + + If the `db_name` database already exists then: + + - If clause is specified, ClickHouse doesn't create a new database and doesn't throw an exception. + - If clause is not specified, then ClickHouse doesn't create a new database and throw and exception. + +- `ON CLUSTER` + + ClickHouse creates the `db_name` database on all the servers of a specified cluster. + +- `ENGINE` + + - [MySQL](../database_engines/mysql.md) + + Allows to retrieve data from the remote MySQL server. + + By default, ClickHouse uses its own [database engine](../database_engines/index.md). ## CREATE TABLE {#create-table-query} @@ -82,10 +99,7 @@ It is not possible to set default values for elements in nested data structures. ### TTL expression -Can be specified only for MergeTree-family tables. An expression for setting storage time for values. It must depends on `Date` or `DateTime` column and has one `Date` or `DateTime` column as a result. Example: - `TTL date + INTERVAL 1 DAY` - -You are not allowed to set TTL for key columns. For more details, see [TTL for columns and tables](../operations/table_engines/mergetree.md) +Defines storage time for values. Can be specified only for MergeTree-family tables. For the detailed description, see [TTL for columns and tables](../operations/table_engines/mergetree.md#table_engine-mergetree-ttl). ## Column Compression Codecs diff --git a/docs/en/query_language/functions/date_time_functions.md b/docs/en/query_language/functions/date_time_functions.md index 8ae05caf935..e8716d8c542 100644 --- a/docs/en/query_language/functions/date_time_functions.md +++ b/docs/en/query_language/functions/date_time_functions.md @@ -95,6 +95,12 @@ Returns the date. Rounds down a date or date with time to the nearest Monday. Returns the date. +## toStartOfWeek(t[,mode]) + +Rounds down a date or date with time to the nearest Sunday or Monday by mode. +Returns the date. +The mode argument works exactly like the mode argument to toWeek(). For the single-argument syntax, a mode value of 0 is used. + ## toStartOfDay Rounds down a date with time to the start of the day. @@ -169,6 +175,72 @@ Converts a date or date with time to a UInt16 number containing the ISO Year num Converts a date or date with time to a UInt8 number containing the ISO Week number. +## toWeek(date[,mode]) +This function returns the week number for date or datetime. The two-argument form of toWeek() enables you to specify whether the week starts on Sunday or Monday and whether the return value should be in the range from 0 to 53 or from 1 to 53. If the mode argument is omitted, the default mode is 0. +`toISOWeek() `is a compatibility function that is equivalent to `toWeek(date,3)`. +The following table describes how the mode argument works. + +| Mode | First day of week | Range | Week 1 is the first week … | +| ----------- | -------- | -------- | ------------------ | +|0|Sunday|0-53|with a Sunday in this year +|1|Monday|0-53|with 4 or more days this year +|2|Sunday|1-53|with a Sunday in this year +|3|Monday|1-53|with 4 or more days this year +|4|Sunday|0-53|with 4 or more days this year +|5|Monday|0-53|with a Monday in this year +|6|Sunday|1-53|with 4 or more days this year +|7|Monday|1-53|with a Monday in this year +|8|Sunday|1-53|contains January 1 +|9|Monday|1-53|contains January 1 + +For mode values with a meaning of “with 4 or more days this year,” weeks are numbered according to ISO 8601:1988: + +- If the week containing January 1 has 4 or more days in the new year, it is week 1. + +- Otherwise, it is the last week of the previous year, and the next week is week 1. + +For mode values with a meaning of “contains January 1”, the week contains January 1 is week 1. It doesn't matter how many days in the new year the week contained, even if it contained only one day. + +``` +toWeek(date, [, mode][, Timezone]) +``` +**Parameters** + +- `date` – Date or DateTime. +- `mode` – Optional parameter, Range of values is [0,9], default is 0. +- `Timezone` – Optional parameter, it behaves like any other conversion function. + +**Example** + +``` sql +SELECT toDate('2016-12-27') AS date, toWeek(date) AS week0, toWeek(date,1) AS week1, toWeek(date,9) AS week9; +``` + +``` +┌───────date─┬─week0─┬─week1─┬─week9─┐ +│ 2016-12-27 │ 52 │ 52 │ 1 │ +└────────────┴───────┴───────┴───────┘ +``` + +## toYearWeek(date[,mode]) +Returns year and week for a date. The year in the result may be different from the year in the date argument for the first and the last week of the year. + +The mode argument works exactly like the mode argument to toWeek(). For the single-argument syntax, a mode value of 0 is used. + +`toISOYear() `is a compatibility function that is equivalent to `intDiv(toYearWeek(date,3),100)`. + +**Example** + +``` sql +SELECT toDate('2016-12-27') AS date, toYearWeek(date) AS yearWeek0, toYearWeek(date,1) AS yearWeek1, toYearWeek(date,9) AS yearWeek9; +``` + +``` +┌───────date─┬─yearWeek0─┬─yearWeek1─┬─yearWeek9─┐ +│ 2016-12-27 │ 201652 │ 201652 │ 201701 │ +└────────────┴───────────┴───────────┴───────────┘ +``` + ## now Accepts zero arguments and returns the current time at one of the moments of request execution. diff --git a/docs/en/query_language/functions/ip_address_functions.md b/docs/en/query_language/functions/ip_address_functions.md index 3fb97e60c1c..ce58a187853 100644 --- a/docs/en/query_language/functions/ip_address_functions.md +++ b/docs/en/query_language/functions/ip_address_functions.md @@ -155,7 +155,6 @@ Accepts an IPv4 and an UInt8 value containing the [CIDR](https://en.wikipedia.or ```sql SELECT IPv4CIDRToRange(toIPv4('192.168.5.2'), 16) ``` - ``` ┌─IPv4CIDRToRange(toIPv4('192.168.5.2'), 16)─┐ │ ('192.168.0.0','192.168.255.255') │ diff --git a/docs/en/query_language/functions/string_search_functions.md b/docs/en/query_language/functions/string_search_functions.md index 71df498d994..fb02a13c3a0 100644 --- a/docs/en/query_language/functions/string_search_functions.md +++ b/docs/en/query_language/functions/string_search_functions.md @@ -108,7 +108,7 @@ For case-insensitive search or/and in UTF-8 format use functions `ngramDistanceC ## ngramSearch(haystack, needle) -Same as `ngramDistance` but calculates the non-symmetric difference between `needle` and `haystack` -- the number of n-grams from needle minus the common number of n-grams normalized by the number of `needle` n-grams. Can be useful for fuzzy string search. +Same as `ngramDistance` but calculates the non-symmetric difference between `needle` and `haystack` -- the number of n-grams from needle minus the common number of n-grams normalized by the number of `needle` n-grams. The closer to one, the more likely `needle` is in the `haystack`. Can be useful for fuzzy string search. For case-insensitive search or/and in UTF-8 format use functions `ngramSearchCaseInsensitive, ngramSearchUTF8, ngramSearchCaseInsensitiveUTF8`. diff --git a/docs/en/query_language/functions/url_functions.md b/docs/en/query_language/functions/url_functions.md index 19b12bd5b21..93edf705e7e 100644 --- a/docs/en/query_language/functions/url_functions.md +++ b/docs/en/query_language/functions/url_functions.md @@ -12,7 +12,7 @@ Returns the protocol. Examples: http, ftp, mailto, magnet... ### domain -Gets the domain. +Gets the domain. Cut scheme with size less than 16 bytes. ### domainWithoutWWW diff --git a/docs/en/query_language/operators.md b/docs/en/query_language/operators.md index 00a1cc5fc9e..4e79c9e805f 100644 --- a/docs/en/query_language/operators.md +++ b/docs/en/query_language/operators.md @@ -65,7 +65,7 @@ Groups of operators are listed in order of priority (the higher it is in the lis `a GLOBAL NOT IN ...` – The `globalNotIn(a, b) function.` -## Operator for Working With Dates and Times +## Operator for Working With Dates and Times {#operators-datetime} ``` sql EXTRACT(part FROM date); @@ -94,13 +94,13 @@ SELECT EXTRACT(MONTH FROM toDate('2017-06-15')); SELECT EXTRACT(YEAR FROM toDate('2017-06-15')); ``` -In the following example we create a table and insert into it a value with the `DateTime` type. +In the following example we create a table and insert into it a value with the `DateTime` type. ``` sql CREATE TABLE test.Orders ( - OrderId UInt64, - OrderName String, + OrderId UInt64, + OrderName String, OrderDate DateTime ) ENGINE = Log; @@ -110,11 +110,11 @@ ENGINE = Log; INSERT INTO test.Orders VALUES (1, 'Jarlsberg Cheese', toDateTime('2008-10-11 13:23:44')); ``` ``` sql -SELECT - toYear(OrderDate) AS OrderYear, - toMonth(OrderDate) AS OrderMonth, - toDayOfMonth(OrderDate) AS OrderDay, - toHour(OrderDate) AS OrderHour, +SELECT + toYear(OrderDate) AS OrderYear, + toMonth(OrderDate) AS OrderMonth, + toDayOfMonth(OrderDate) AS OrderDay, + toHour(OrderDate) AS OrderHour, toMinute(OrderDate) AS OrderMinute, toSecond(OrderDate) AS OrderSecond FROM test.Orders; diff --git a/docs/en/query_language/system.md b/docs/en/query_language/system.md new file mode 100644 index 00000000000..c5f4830723f --- /dev/null +++ b/docs/en/query_language/system.md @@ -0,0 +1,34 @@ +# SYSTEM Queries {#query_language-system} + +- [STOP DISTRIBUTED SENDS](#query_language-system-stop-distributed-sends) +- [FLUSH DISTRIBUTED](#query_language-system-flush-distributed) +- [START DISTRIBUTED SENDS](#query_language-system-start-distributed-sends) + +## Managing Distributed Tables {#query_language-system-distributed} + +ClickHouse can manage [distributed](../operations/table_engines/distributed.md) tables. When a user inserts data into such table, ClickHouse creates a queue of the data which should be sent to servers of the cluster, then asynchronously sends them. You can control the processing of queue by using the requests [STOP DISTRIBUTED SENDS](#query_language-system-stop-distributed-sends), [FLUSH DISTRIBUTED](#query_language-system-flush-distributed) and [START DISTRIBUTED SENDS](#query_language-system-start-distributed-sends). Also, you can synchronously insert distributed data with the `insert_distributed_sync` setting. + + +### STOP DISTRIBUTED SENDS {#query_language-system-stop-distributed-sends} + +Disables background data distributing, when inserting data into the distributed tables. + +``` +SYSTEM STOP DISTRIBUTED SENDS [db.] +``` + +### FLUSH DISTRIBUTED {#query_language-system-flush-distributed} + +Forces ClickHouse to send data to the servers of the cluster in synchronous mode. If some of the servers are not available, ClickHouse throws an exception and stops query processing. When servers are back into operation, you should repeat the query. + +``` +SYSTEM FLUSH DISTRIBUTED [db.] +``` + +### START DISTRIBUTED SENDS {#query_language-system-start-distributed-sends} + +Enables background data distributing, when inserting data into the distributed tables. + +``` +SYSTEM START DISTRIBUTED SENDS [db.] +``` diff --git a/docs/fa/database_engines/index.md b/docs/fa/database_engines/index.md new file mode 120000 index 00000000000..bbdb762a4ad --- /dev/null +++ b/docs/fa/database_engines/index.md @@ -0,0 +1 @@ +../../en/database_engines/index.md \ No newline at end of file diff --git a/docs/fa/database_engines/mysql.md b/docs/fa/database_engines/mysql.md new file mode 120000 index 00000000000..51ac4126e2d --- /dev/null +++ b/docs/fa/database_engines/mysql.md @@ -0,0 +1 @@ +../../en/database_engines/mysql.md \ No newline at end of file diff --git a/docs/fa/operations/settings/settings_users.md b/docs/fa/operations/settings/settings_users.md new file mode 120000 index 00000000000..3a6a7cf6948 --- /dev/null +++ b/docs/fa/operations/settings/settings_users.md @@ -0,0 +1 @@ +../../../en/operations/settings/settings_users.md \ No newline at end of file diff --git a/docs/fa/query_language/system.md b/docs/fa/query_language/system.md new file mode 120000 index 00000000000..6061858c3f2 --- /dev/null +++ b/docs/fa/query_language/system.md @@ -0,0 +1 @@ +../../en/query_language/system.md \ No newline at end of file diff --git a/docs/ru/database_engines/index.md b/docs/ru/database_engines/index.md new file mode 100644 index 00000000000..3190a79017f --- /dev/null +++ b/docs/ru/database_engines/index.md @@ -0,0 +1,9 @@ +# Database Engines + +Database engines provide working with tables. + +By default, ClickHouse uses its native database engine which provides configurable [table engines](../operations/table_engines/index.md) and [SQL dialect](../query_language/syntax.md). + +Also you can use the following database engines: + +- [MySQL](mysql.md) diff --git a/docs/ru/database_engines/mysql.md b/docs/ru/database_engines/mysql.md new file mode 100644 index 00000000000..fd5417ee27d --- /dev/null +++ b/docs/ru/database_engines/mysql.md @@ -0,0 +1,122 @@ +# MySQL + +Allows to connect to some database on remote MySQL server and perform `INSERT` and `SELECT` queries with tables to exchange data between ClickHouse and MySQL. + +The `MySQL` database engine translate queries to the MySQL server, so you can perform operations such as `SHOW TABLES` or `SHOW CREATE TABLE`. + +You cannot perform with tables the following queries: + +- `ATTACH`/`DETACH` +- `DROP` +- `RENAME` +- `CREATE TABLE` +- `ALTER` + + +## Creating a Database + +``` sql +CREATE DATABASE [IF NOT EXISTS] db_name [ON CLUSTER cluster] +ENGINE = MySQL('host:port', 'database', 'user', 'password') +``` + +**Engine Parameters** + +- `host:port` — MySQL server address. +- `database` — Remote database name. +- `user` — MySQL user. +- `password` — User password. + + +## Data Types Support + +MySQL | ClickHouse +------|------------ +UNSIGNED TINYINT | [UInt8](../data_types/int_uint.md) +TINYINT | [Int8](../data_types/int_uint.md) +UNSIGNED SMALLINT | [UInt16](../data_types/int_uint.md) +SMALLINT | [Int16](../data_types/int_uint.md) +UNSIGNED INT, UNSIGNED MEDIUMINT | [UInt32](../data_types/int_uint.md) +INT, MEDIUMINT | [Int32](../data_types/int_uint.md) +UNSIGNED BIGINT | [UInt64](../data_types/int_uint.md) +BIGINT | [Int64](../data_types/int_uint.md) +FLOAT | [Float32](../data_types/float.md) +DOUBLE | [Float64](../data_types/float.md) +DATE | [Date](../data_types/date.md) +DATETIME, TIMESTAMP | [DateTime](../data_types/datetime.md) +BINARY | [FixedString](../data_types/fixedstring.md) + +All other MySQL data types are converted into [String](../data_types/string.md). + +[Nullable](../data_types/nullable.md) data type is supported. + + +## Examples of Use + +Table in MySQL: + +``` +mysql> USE test; +Database changed + +mysql> CREATE TABLE `mysql_table` ( + -> `int_id` INT NOT NULL AUTO_INCREMENT, + -> `float` FLOAT NOT NULL, + -> PRIMARY KEY (`int_id`)); +Query OK, 0 rows affected (0,09 sec) + +mysql> insert into mysql_table (`int_id`, `float`) VALUES (1,2); +Query OK, 1 row affected (0,00 sec) + +mysql> select * from mysql_table; ++--------+-------+ +| int_id | value | ++--------+-------+ +| 1 | 2 | ++--------+-------+ +1 row in set (0,00 sec) +``` + +Database in ClickHouse, exchanging data with the MySQL server: + +```sql +CREATE DATABASE mysql_db ENGINE = MySQL('localhost:3306', 'test', 'my_user', 'user_password') +``` +```sql +SHOW DATABASES +``` +```text +┌─name─────┐ +│ default │ +│ mysql_db │ +│ system │ +└──────────┘ +``` +```sql +SHOW TABLES FROM mysql_db +``` +```text +┌─name─────────┐ +│ mysql_table │ +└──────────────┘ +``` +```sql +SELECT * FROM mysql_db.mysql_table +``` +```text +┌─int_id─┬─value─┐ +│ 1 │ 2 │ +└────────┴───────┘ +``` +```sql +INSERT INTO mysql_db.mysql_table VALUES (3,4) +``` +```sql +SELECT * FROM mysql_db.mysql_table +``` +```text +┌─int_id─┬─value─┐ +│ 1 │ 2 │ +│ 3 │ 4 │ +└────────┴───────┘ +``` diff --git a/docs/ru/operations/settings/query_complexity.md b/docs/ru/operations/settings/query_complexity.md index ae7232d8ae8..24286999685 100644 --- a/docs/ru/operations/settings/query_complexity.md +++ b/docs/ru/operations/settings/query_complexity.md @@ -157,7 +157,7 @@ ## max_ast_elements Максимальное количество элементов синтаксического дерева запроса. Если превышено - кидается исключение. -Аналогично, проверяется уже после парсинга запроса. По умолчанию: 10 000. +Аналогично, проверяется уже после парсинга запроса. По умолчанию: 50 000. ## max_rows_in_set diff --git a/docs/ru/operations/settings/settings_users.md b/docs/ru/operations/settings/settings_users.md new file mode 100644 index 00000000000..85233f19baa --- /dev/null +++ b/docs/ru/operations/settings/settings_users.md @@ -0,0 +1,128 @@ +# Настройки пользователей + +Раздел `users` конфигурационного файла `user.xml` содержит настройки для пользователей. + +Структура раздела `users`: + +``` + + + + + + + + + + + profile_name + + default + + + + + expression + + + + + + +``` + +### user_name/password + +Пароль можно указать в текстовом виде или в виде SHA256 (шестнадцатеричный формат). + +- Чтобы назначить пароль в текстовом виде (**не рекомендуем**), поместите его в элемент `password`. + + Например, `qwerty`. Пароль можно оставить пустым. + +- Чтобы назначить пароль в виде SHA256, поместите хэш в элемент `password_sha256_hex`. + + Например, `65e84be33532fb784c48129675f9eff3a682b27168c0ea744b2cf58ee02337c5`. + + Пример создания пароля в командной строке: + + ``` + PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha256sum | tr -d '-' + ``` + + Первая строка результата — пароль. Вторая строка — соответствующий ему хэш SHA256. + +### user_name/networks + +Список сетей, из которых пользователь может подключиться к серверу ClickHouse. + +Каждый элемент списка имеет одну из следующих форм: + +- `` — IP-адрес или маска подсети. + + Примеры: `213.180.204.3`, `10.0.0.1/8`, `10.0.0.1/255.255.255.0`, `2a02:6b8::3`, `2a02:6b8::3/64`, `2a02:6b8::3/ffff:ffff:ffff:ffff::`. + +- `` — Имя хоста. + + Пример: `server01.yandex.ru`. + + Для проверки доступа выполняется DNS-запрос, и все возвращенные IP-адреса сравниваются с адресом клиента. + +- `` — Регулярное выражение для имен хостов. + + Пример, `^server\d\d-\d\d-\d\.yandex\.ru$` + + Для проверки доступа выполняется [DNS запрос PTR](https://en.wikipedia.org/wiki/Reverse_DNS_lookup) для адреса клиента, а затем применяется заданное регулярное выражение. Затем, для результатов запроса PTR выполняется другой DNS-запрос и все полученные адреса сравниваются с адресом клиента. Рекомендуем завершать регулярное выражение символом $. + +Все результаты DNS-запросов кэшируются до перезапуска сервера. + +**Примеры** + +Чтобы открыть доступ пользователю из любой сети, укажите: + +``` +::/0 +``` + +!!! warning "Внимание" + Открывать доступ из любой сети небезопасно, если у вас нет правильно настроенного брандмауэра или сервер не отключен от интернета. + +Чтобы открыть только локальный доступ, укажите: + +``` +::1 +127.0.0.1 +``` + +### user_name/profile + +Пользователю можно назначить профиль настроек. Профили настроек конфигурируются в отдельной секции файла `users.xml`. Подробнее читайте в разделе [Профили настроек](settings_profiles.md). + +### user_name/quota + +Квотирование позволяет отслеживать или ограничивать использование ресурсов в течение определённого периода времени. Квоты настраиваются в разделе `quotas` конфигурационного файла `users.xml`. + +Пользователю можно назначить квоты. Подробное описание настройки квот смотрите в разделе [Квоты](../quotas.md#quotas). + +### user_name/databases + +В этом разделе вы можете ограничить выдачу ClickHouse запросами `SELECT` для конкретного пользователя, таким образом реализуя базовую защиту на уровне строк. + +**Пример** + +Следующая конфигурация задаёт, что пользователь `user1` в результате запросов `SELECT` может получать только те строки `table1`, в которых значение поля `id` равно 1000. + +``` + + + + + id = 1000 + + + + +``` + +Элемент `filter` содержать любое выражение, возвращающее значение типа [UInt8](../../data_types/int_uint.md). Обычно он содержит сравнения и логические операторы. Строки `database_name.table1`, для которых фильтр возвращает 0 не выдаются пользователю. Фильтрация несовместима с операциями `PREWHERE` и отключает оптимизацию `WHERE→PREWHERE`. + +[Оригинальная статья](https://clickhouse.yandex/docs/ru/operations/settings/settings_users/) diff --git a/docs/ru/operations/table_engines/kafka.md b/docs/ru/operations/table_engines/kafka.md index bdbc13e171a..3fe2e4d5cba 100644 --- a/docs/ru/operations/table_engines/kafka.md +++ b/docs/ru/operations/table_engines/kafka.md @@ -97,6 +97,7 @@ Kafka(kafka_broker_list, kafka_topic_list, kafka_group_name, kafka_format 3. Создайте материализованное представление, которое преобразует данные от движка и помещает их в ранее созданную таблицу. Когда к движку присоединяется материализованное представление (`MATERIALIZED VIEW`), оно начинает в фоновом режиме собирать данные. Это позволяет непрерывно получать сообщения от Kafka и преобразовывать их в необходимый формат с помощью `SELECT`. +Материализованных представлений у одной kafka таблицы может быть сколько угодно, они не считывают данные из таблицы kafka непосредственно, а получают новые записи (блоками), таким образом можно писать в несколько таблиц с разным уровнем детализации (с группировкой - агрегацией и без). Пример: diff --git a/docs/ru/query_language/agg_functions/reference.md b/docs/ru/query_language/agg_functions/reference.md index faf7936c984..6247b74f657 100644 --- a/docs/ru/query_language/agg_functions/reference.md +++ b/docs/ru/query_language/agg_functions/reference.md @@ -83,7 +83,7 @@ binary decimal SELECT groupBitAnd(num) FROM t ``` -Где `num` – столбец с тестовыми данными. +Где `num` — столбец с тестовыми данными. Результат: @@ -126,7 +126,7 @@ binary decimal SELECT groupBitOr(num) FROM t ``` -Где `num` – столбец с тестовыми данными. +Где `num` — столбец с тестовыми данными. Результат: @@ -169,7 +169,7 @@ binary decimal SELECT groupBitXor(num) FROM t ``` -Где `num` – столбец с тестовыми данными. +Где `num` — столбец с тестовыми данными. Результат: @@ -199,7 +199,7 @@ groupBitmap(expr) Тестовые данные: ``` -userid +UserID 1 1 2 @@ -209,7 +209,7 @@ userid Запрос: ``` -SELECT groupBitmap(userid) as num FROM t +SELECT groupBitmap(UserID) as num FROM t ``` Результат: @@ -300,6 +300,98 @@ GROUP BY timeslot └─────────────────────┴──────────────────────────────────────────────┘ ``` +## skewPop + +Вычисляет [коэффициент асимметрии](https://ru.wikipedia.org/wiki/Коэффициент_асимметрии) для последовательности. + +``` +skewPop(expr) +``` + +**Параметры** + +`expr` — [Выражение](../syntax.md#syntax-expressions), возвращающее число. + +**Возвращаемое значение** + +Коэффициент асимметрии заданного распределения. Тип — [Float64](../../data_types/float.md) + +**Пример** + +```sql +SELECT skewPop(value) FROM series_with_value_column +``` + +## skewSamp + +Вычисляет [выборочный коэффициент асимметрии](https://ru.wikipedia.org/wiki/Статистика_(функция_выборки)) для последовательности. + +Он представляет собой несмещенную оценку асимметрии случайной величины, если переданные значения образуют ее выборку. + +``` +skewSamp(expr) +``` + +**Параметры** + +`expr` — [Выражение](../syntax.md#syntax-expressions), возвращающее число. + +**Возвращаемое значение** + +Коэффициент асимметрии заданного распределения. Тип — [Float64](../../data_types/float.md). Если `n <= 1` (`n` — размер выборки), тогда функция возвращает `nan`. + +**Пример** + +```sql +SELECT skewSamp(value) FROM series_with_value_column +``` + +## kurtPop + +Вычисляет [коэффициент эксцесса](https://ru.wikipedia.org/wiki/Коэффициент_эксцесса) последовательности. + +``` +kurtPop(expr) +``` + +**Параметры** + +`expr` — [Выражение](../syntax.md#syntax-expressions), возвращающее число. + +**Возвращаемое значение** + +Коэффициент эксцесса заданного распределения. Тип — [Float64](../../data_types/float.md) + +**Пример** + +```sql +SELECT kurtPop(value) FROM series_with_value_column +``` + +## kurtSamp + +Вычисляет [выборочный коэффициент эксцесса](https://ru.wikipedia.org/wiki/Статистика_(функция_выборки)) для последовательности. + +Он представляет собой несмещенную оценку эксцесса случайной величины, если переданные значения образуют ее выборку. + +``` +kurtSamp(expr) +``` + +**Параметры** + +`expr` — [Выражение](../syntax.md#syntax-expressions), возвращающее число. + +**Возвращаемое значение** + +Коэффициент эксцесса заданного распределения. Тип — [Float64](../../data_types/float.md). Если `n <= 1` (`n` — размер выборки), тогда функция возвращает `nan`. + +**Пример** + +```sql +SELECT kurtSamp(value) FROM series_with_value_column +``` + ## timeSeriesGroupSum(uid, timestamp, value) {#agg_function-timeseriesgroupsum} `timeSeriesGroupSum` агрегирует временные ряды в которых не совпадают моменты. diff --git a/docs/ru/query_language/functions/geo.md b/docs/ru/query_language/functions/geo.md index 66759e2bd3b..33092cf804b 100644 --- a/docs/ru/query_language/functions/geo.md +++ b/docs/ru/query_language/functions/geo.md @@ -152,4 +152,35 @@ SELECT geohashDecode('ezs42') AS res └─────────────────────────────────┘ ``` +## geoToH3 + +Получает H3 индекс точки (lon, lat) с заданным разрешением + +``` +geoToH3(lon, lat, resolution) +``` + +**Входные значения** + +- `lon` - географическая долгота. Тип данных — [Float64](../../data_types/float.md). +- `lat` - географическая широта. Тип данных — [Float64](../../data_types/float.md). +- `resolution` - требуемое разрешение индекса. Тип данных — [UInt8](../../data_types/int_uint.md). Диапазон возможных значение — `[0, 15]`. + +**Возвращаемые значения** + +Возвращает значение с типом [UInt64] (../../data_types/int_uint.md). +`0` в случае ошибки. +Иначе возвращается индексный номер шестиугольника. + +**Пример** + +``` sql +SELECT geoToH3(37.79506683, 55.71290588, 15) as h3Index +``` +``` +┌────────────h3Index─┐ +│ 644325524701193974 │ +└────────────────────┘ +``` + [Оригинальная статья](https://clickhouse.yandex/docs/ru/query_language/functions/geo/) diff --git a/docs/ru/query_language/functions/ip_address_functions.md b/docs/ru/query_language/functions/ip_address_functions.md index 647dcb5fdb2..57c11b46d81 100644 --- a/docs/ru/query_language/functions/ip_address_functions.md +++ b/docs/ru/query_language/functions/ip_address_functions.md @@ -146,32 +146,30 @@ SELECT └─────────────────────────────────────┴─────────────────────┘ ``` -## IPv4CIDRtoIPv4Range(ipv4, cidr), +## IPv4CIDRToRange(ipv4, cidr), Принимает на вход IPv4 и значение `UInt8`, содержащее [CIDR](https://ru.wikipedia.org/wiki/Бесклассовая_адресация). Возвращает кортеж с двумя IPv4, содержащими нижний и более высокий диапазон подсети. ```sql -SELECT IPv4CIDRtoIPv4Range(toIPv4('192.168.5.2'), 16) +SELECT IPv4CIDRToRange(toIPv4('192.168.5.2'), 16) +``` +```text +┌─IPv4CIDRToRange(toIPv4('192.168.5.2'), 16)─┐ +│ ('192.168.0.0','192.168.255.255') │ +└────────────────────────────────────────────┘ ``` -``` -┌─IPv4CIDRtoIPv4Range(toIPv4('192.168.5.2'), 16)─┐ -│ ('192.168.0.0','192.168.255.255') │ -└────────────────────────────────────────────────┘ -``` - -## IPv6CIDRtoIPv6Range(ipv6, cidr), +## IPv6CIDRToRange(ipv6, cidr), Принимает на вход IPv6 и значение `UInt8`, содержащее CIDR. Возвращает кортеж с двумя IPv6, содержащими нижний и более высокий диапазон подсети. ```sql -SELECT IPv6CIDRtoIPv6Range(toIPv6('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 32); +SELECT IPv6CIDRToRange(toIPv6('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 32) ``` - -``` -┌─IPv6CIDRtoIPv6Range(toIPv6('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 32)─┐ -│ ('2001:db8::','2001:db8:ffff:ffff:ffff:ffff:ffff:ffff') │ -└────────────────────────────────────────────────────────────────────────────┘ +```text +┌─IPv6CIDRToRange(toIPv6('2001:0db8:0000:85a3:0000:0000:ac1f:8001'), 32)─┐ +│ ('2001:db8::','2001:db8:ffff:ffff:ffff:ffff:ffff:ffff') │ +└────────────────────────────────────────────────────────────────────────┘ ``` ## toIPv4(string) diff --git a/docs/ru/query_language/functions/string_search_functions.md b/docs/ru/query_language/functions/string_search_functions.md index 0301b094c86..7e94e378814 100644 --- a/docs/ru/query_language/functions/string_search_functions.md +++ b/docs/ru/query_language/functions/string_search_functions.md @@ -97,7 +97,7 @@ ## ngramSearch(haystack, needle) -То же, что и `ngramDistance`, но вычисляет несимметричную разность между `needle` и `haystack` -- количество n-грамм из `needle` минус количество общих n-грамм, нормированное на количество n-грамм из `needle`. Может быть использовано для приближенного поиска. +То же, что и `ngramDistance`, но вычисляет несимметричную разность между `needle` и `haystack` -- количество n-грамм из `needle` минус количество общих n-грамм, нормированное на количество n-грамм из `needle`. Чем ближе результат к единице, тем вероятнее, что `needle` внутри `haystack`. Может быть использовано для приближенного поиска. Для поиска без учета регистра и/или в формате UTF-8 используйте функции `ngramSearchCaseInsensitive, ngramSearchUTF8, ngramSearchCaseInsensitiveUTF8`. diff --git a/docs/ru/query_language/functions/url_functions.md b/docs/ru/query_language/functions/url_functions.md index 4b4fdc9adda..1897d1b28a3 100644 --- a/docs/ru/query_language/functions/url_functions.md +++ b/docs/ru/query_language/functions/url_functions.md @@ -10,7 +10,7 @@ Возвращает протокол. Примеры: http, ftp, mailto, magnet... ### domain -Возвращает домен. +Возвращает домен. Отсекает схему размером не более 16 байт. ### domainWithoutWWW Возвращает домен, удалив не более одного 'www.' с начала, если есть. diff --git a/docs/ru/query_language/system.md b/docs/ru/query_language/system.md new file mode 100644 index 00000000000..fcf6fb8eced --- /dev/null +++ b/docs/ru/query_language/system.md @@ -0,0 +1,33 @@ +# SYSTEM Queries {#query_language-system} + +- [STOP DISTRIBUTED SENDS](#query_language-system-stop-distributed-sends) +- [FLUSH DISTRIBUTED](#query_language-system-flush-distributed) +- [START DISTRIBUTED SENDS](#query_language-system-start-distributed-sends) + +## Managing Distributed Tables {#query_language-system-distributed} + +ClickHouse can manage [distributed](../operations/table_engines/distributed.md) tables. When a user inserts data into such table, ClickHouse creates a queue of the data which should be sent to servers of the cluster, then asynchronously sends them. You can control the processing of queue by using the requests [STOP DISTRIBUTED SENDS](#query_language-system-stop-distributed-sends), [FLUSH DISTRIBUTED](#query_language-system-flush-distributed) and [START DISTRIBUTED SENDS](#query_language-system-start-distributed-sends). + +### STOP DISTRIBUTED SENDS {#query_language-system-stop-distributed-sends} + +Disables asynchronous distribution of data between servers of the cluster. + +``` +SYSTEM STOP DISTRIBUTED SENDS [db.] +``` + +### FLUSH DISTRIBUTED {#query_language-system-flush-distributed} + +Forces ClickHouse to send data to the servers of the cluster in synchronous mode. If some of the servers are not available, ClickHouse throws an exception and stops query processing. When servers back into operation, you should repeat the query. + +``` +SYSTEM FLUSH DISTRIBUTED [db.] +``` + +### START DISTRIBUTED SENDS {#query_language-system-start-distributed-sends} + +Enables asynchronous distribution of data between servers of cluster. + +``` +SYSTEM START DISTRIBUTED SENDS [db.] +``` diff --git a/docs/toc_en.yml b/docs/toc_en.yml index 7ca367a0cec..d75f81a556c 100644 --- a/docs/toc_en.yml +++ b/docs/toc_en.yml @@ -61,6 +61,10 @@ nav: - 'IPv4': 'data_types/domains/ipv4.md' - 'IPv6': 'data_types/domains/ipv6.md' +- 'Database Engines': + - 'Introduction': 'database_engines/index.md' + - 'MySQL': 'database_engines/mysql.md' + - 'Table Engines': - 'Introduction': 'operations/table_engines/index.md' - 'MergeTree Family': @@ -104,6 +108,7 @@ nav: - 'INSERT INTO': 'query_language/insert_into.md' - 'CREATE': 'query_language/create.md' - 'ALTER': 'query_language/alter.md' + - 'SYSTEM': 'query_language/system.md' - 'Other Kinds of Queries': 'query_language/misc.md' - 'Functions': - 'Introduction': 'query_language/functions/index.md' diff --git a/docs/toc_fa.yml b/docs/toc_fa.yml index 42419874dd8..70a0f222d4d 100644 --- a/docs/toc_fa.yml +++ b/docs/toc_fa.yml @@ -61,6 +61,10 @@ nav: - 'IPv4': 'data_types/domains/ipv4.md' - 'IPv6': 'data_types/domains/ipv6.md' +- 'Database Engines': + - 'Introduction': 'database_engines/index.md' + - 'MySQL': 'database_engines/mysql.md' + - 'Table Engines': - 'Introduction': 'operations/table_engines/index.md' - 'MergeTree Family': @@ -104,6 +108,7 @@ nav: - 'INSERT INTO': 'query_language/insert_into.md' - 'CREATE': 'query_language/create.md' - 'ALTER': 'query_language/alter.md' + - 'SYSTEM': 'query_language/system.md' - 'Other Kinds of Queries': 'query_language/misc.md' - 'Functions': - 'Introduction': 'query_language/functions/index.md' @@ -187,6 +192,7 @@ nav: - 'Restrictions on Query Complexity': 'operations/settings/query_complexity.md' - 'Settings': 'operations/settings/settings.md' - 'Settings Profiles': 'operations/settings/settings_profiles.md' + - 'User Settings': 'operations/settings/settings_users.md' - 'Constraints on Settings': 'operations/settings/constraints_on_settings.md' - 'Utilities': - 'Overview': 'operations/utils/index.md' diff --git a/docs/toc_ru.yml b/docs/toc_ru.yml index 6a06b58f53c..d2f463fcc85 100644 --- a/docs/toc_ru.yml +++ b/docs/toc_ru.yml @@ -62,6 +62,10 @@ nav: - 'IPv4': 'data_types/domains/ipv4.md' - 'IPv6': 'data_types/domains/ipv6.md' +- 'Движки баз данных': + - 'Введение': 'database_engines/index.md' + - 'MySQL': 'database_engines/mysql.md' + - 'Движки таблиц': - 'Введение': 'operations/table_engines/index.md' - 'Семейство MergeTree': @@ -105,6 +109,7 @@ nav: - 'INSERT INTO': 'query_language/insert_into.md' - 'CREATE': 'query_language/create.md' - 'ALTER': 'query_language/alter.md' + - 'SYSTEM': 'query_language/system.md' - 'Прочие виды запросов': 'query_language/misc.md' - 'Функции': - 'Введение': 'query_language/functions/index.md' @@ -189,6 +194,7 @@ nav: - 'Настройки': 'operations/settings/settings.md' - 'Ограничения на изменение настроек': 'operations/settings/constraints_on_settings.md' - 'Профили настроек': 'operations/settings/settings_profiles.md' + - 'Настройки пользователей': 'operations/settings/settings_users.md' - 'Утилиты': - 'Введение': 'operations/utils/index.md' - 'clickhouse-copier': 'operations/utils/clickhouse-copier.md' diff --git a/docs/toc_zh.yml b/docs/toc_zh.yml index 6c2db56f314..40b1c97d2a8 100644 --- a/docs/toc_zh.yml +++ b/docs/toc_zh.yml @@ -60,6 +60,10 @@ nav: - 'IPv4': 'data_types/domains/ipv4.md' - 'IPv6': 'data_types/domains/ipv6.md' +- 'Database Engines': + - 'Introduction': 'database_engines/index.md' + - 'MySQL': 'database_engines/mysql.md' + - 'Table Engines': - 'Introduction': 'operations/table_engines/index.md' - 'MergeTree Family': @@ -103,6 +107,7 @@ nav: - 'INSERT INTO': 'query_language/insert_into.md' - 'CREATE': 'query_language/create.md' - 'ALTER': 'query_language/alter.md' + - 'SYSTEM': 'query_language/system.md' - 'Other kinds of queries': 'query_language/misc.md' - 'Functions': - '介绍': 'query_language/functions/index.md' @@ -186,6 +191,7 @@ nav: - 'Restrictions on query complexity': 'operations/settings/query_complexity.md' - 'Settings': 'operations/settings/settings.md' - 'Settings profiles': 'operations/settings/settings_profiles.md' + - 'User Settings': 'operations/settings/settings_users.md' - 'Constraints on Settings': 'operations/settings/constraints_on_settings.md' - 'Utilities': - 'Overview': 'operations/utils/index.md' diff --git a/docs/zh/database_engines/index.md b/docs/zh/database_engines/index.md new file mode 120000 index 00000000000..bbdb762a4ad --- /dev/null +++ b/docs/zh/database_engines/index.md @@ -0,0 +1 @@ +../../en/database_engines/index.md \ No newline at end of file diff --git a/docs/zh/database_engines/mysql.md b/docs/zh/database_engines/mysql.md new file mode 120000 index 00000000000..51ac4126e2d --- /dev/null +++ b/docs/zh/database_engines/mysql.md @@ -0,0 +1 @@ +../../en/database_engines/mysql.md \ No newline at end of file diff --git a/docs/zh/development/architecture.md b/docs/zh/development/architecture.md deleted file mode 120000 index abda4dd48a8..00000000000 --- a/docs/zh/development/architecture.md +++ /dev/null @@ -1 +0,0 @@ -../../en/development/architecture.md \ No newline at end of file diff --git a/docs/zh/development/architecture.md b/docs/zh/development/architecture.md new file mode 100644 index 00000000000..ad00ce932d1 --- /dev/null +++ b/docs/zh/development/architecture.md @@ -0,0 +1,194 @@ +# ClickHouse 架构概述 + +ClickHouse 是一个真正的列式数据库管理系统(DBMS)。在 ClickHouse 中,数据始终是按列存储的,包括失量(向量或列块)执行的过程。只要有可能,操作都是基于失量进行分派的,而不是单个的值,这被称为“矢量化查询执行”,它有利于降低实际的数据处理开销。 + +> 这个想法并不新鲜,其可以追溯到 `APL` 编程语言及其后代:`A +`、`J`、`K` 和 `Q`。失量编程被大量用于科学数据处理中。即使在关系型数据库中,这个想法也不是什么新的东西:比如,失量编程也被大量用于 `Vectorwise` 系统中。 + +通常有两种不同的加速查询处理的方法:矢量化查询执行和运行时代码生成。在后者中,动态地为每一类查询生成代码,消除了间接分派和动态分派。这两种方法中,并没有哪一种严格地比另一种好。运行时代码生成可以更好地将多个操作融合在一起,从而充分利用 CPU 执行单元和流水线。矢量化查询执行不是特别实用,因为它涉及必须写到缓存并读回的临时向量。如果 L2 缓存容纳不下临时数据,那么这将成为一个问题。但矢量化查询执行更容易利用 CPU 的 SIMD 功能。朋友写的一篇[研究论文](http://15721.courses.cs.cmu.edu/spring2016/papers/p5-sompolski.pdf)表明,将两种方法结合起来是更好的选择。ClickHouse 使用了矢量化查询执行,同时初步提供了有限的运行时动态代码生成。 + +## 列(Columns) + +要表示内存中的列(实际上是列块),需使用 `IColumn` 接口。该接口提供了用于实现各种关系操作符的辅助方法。几乎所有的操作都是不可变的:这些操作不会更改原始列,但是会创建一个新的修改后的列。比如,`IColumn::filter` 方法接受过滤字节掩码,用于 `WHERE` 和 `HAVING` 关系操作符中。另外的例子:`IColumn::permute` 方法支持 `ORDER BY` 实现,`IColumn::cut` 方法支持 `LIMIT` 实现等等。 + +不同的 `IColumn` 实现(`ColumnUInt8`、`ColumnString` 等)负责不同的列内存布局。内存布局通常是一个连续的数组。对于数据类型为整型的列,只是一个连续的数组,比如 `std::vector`。对于 `String` 列和 `Array` 列,则由两个向量组成:其中一个向量连续存储所有的 `String` 或数组元素,另一个存储每一个 `String` 或 `Array` 的起始元素在第一个向量中的偏移。而 `ColumnConst` 则仅在内存中存储一个值,但是看起来像一个列。 + +## Field + +尽管如此,有时候也可能需要处理单个值。表示单个值,可以使用 `Field`。`Field` 是 `UInt64`、`Int64`、`Float64`、`String` 和 `Array` 组成的联合。`IColumn` 拥有 `operator[]` 方法来获取第 `n` 个值成为一个 `Field`,同时也拥有 `insert` 方法将一个 `Field` 追加到一个列的末尾。这些方法并不高效,因为它们需要处理表示单一值的临时 `Field` 对象,但是有更高效的方法比如 `insertFrom` 和 `insertRangeFrom` 等。 + +`Field` 中并没有足够的关于一个表(table)的特定数据类型的信息。比如,`UInt8`、`UInt16`、`UInt32` 和 `UInt64` 在 `Field` 中均表示为 `UInt64`。 + +## 抽象漏洞 + +`IColumn` 具有用于数据的常见关系转换的方法,但这些方法并不能够满足所有需求。比如,`ColumnUInt64` 没有用于计算两列和的方法,`ColumnString` 没有用于进行子串搜索的方法。这些无法计算的例程在 `Icolumn` 之外实现。 + +列(Columns)上的各种函数可以通过使用 `Icolumn` 的方法来提取 `Field` 值,或根据特定的 `Icolumn` 实现的数据内存布局的知识,以一种通用但不高效的方式实现。为此,函数将会转换为特定的 `IColumn` 类型并直接处理内部表示。比如,`ColumnUInt64` 具有 `getData` 方法,该方法返回一个指向列的内部数组的引用,然后一个单独的例程可以直接读写或填充该数组。实际上,“抽象漏洞(leaky abstractions)”允许我们以更高效的方式来实现各种特定的例程。 + +## 数据类型 + +`IDataType` 负责序列化和反序列化:读写二进制或文本形式的列或单个值构成的块。`IDataType` 直接与表的数据类型相对应。比如,有 `DataTypeUInt32`、`DataTypeDateTime`、`DataTypeString` 等数据类型。 + +`IDataType` 与 `IColumn` 之间的关联并不大。不同的数据类型在内存中能够用相同的 `IColumn` 实现来表示。比如,`DataTypeUInt32` 和 `DataTypeDateTime` 都是用 `ColumnUInt32` 或 `ColumnConstUInt32` 来表示的。另外,相同的数据类型也可以用不同的 `IColumn` 实现来表示。比如,`DataTypeUInt8` 既可以使用 `ColumnUInt8` 来表示,也可以使用过 `ColumnConstUInt8` 来表示。 + +`IDataType` 仅存储元数据。比如,`DataTypeUInt8` 不存储任何东西(除了 vptr);`DataTypeFixedString` 仅存储 `N`(固定长度字符串的串长度)。 + +`IDataType` 具有针对各种数据格式的辅助函数。比如如下一些辅助函数:序列化一个值并加上可能的引号;序列化一个值用于 JSON 格式;序列化一个值作为 XML 格式的一部分。辅助函数与数据格式并没有直接的对应。比如,两种不同的数据格式 `Pretty` 和 `TabSeparated` 均可以使用 `IDataType` 接口提供的 `serializeTextEscaped` 这一辅助函数。 + +## 块(Block) + +`Block` 是表示内存中表的子集(chunk)的容器,是由三元组:`(IColumn, IDataType, 列名)` 构成的集合。在查询执行期间,数据是按 `Block` 进行处理的。如果我们有一个 `Block`,那么就有了数据(在 `IColumn` 对象中),有了数据的类型信息告诉我们如何处理该列,同时也有了列名(来自表的原始列名,或人为指定的用于临时计算结果的名字)。 + +当我们遍历一个块中的列进行某些函数计算时,会把结果列加入到块中,但不会更改函数参数中的列,因为操作是不可变的。之后,不需要的列可以从块中删除,但不是修改。这对于消除公共子表达式非常方便。 + +`Block` 用于处理数据块。注意,对于相同类型的计算,列名和类型对不同的块保持相同,仅列数据不同。最好把块数据(block data)和块头(block header)分离开来,因为小块大小会因复制共享指针和列名而带来很高的临时字符串开销。 + +## 块流(Block Streams) + +块流用于处理数据。我们可以使用块流从某个地方读取数据,执行数据转换,或将数据写到某个地方。`IBlockInputStream` 具有 `read` 方法,其能够在数据可用时获取下一个块。`IBlockOutputStream` 具有 `write` 方法,其能够将块写到某处。 + +块流负责: + +1. 读或写一个表。表仅返回一个流用于读写块。 +2. 完成数据格式化。比如,如果你打算将数据以 `Pretty` 格式输出到终端,你可以创建一个块输出流,将块写入该流中,然后进行格式化。 +3. 执行数据转换。假设你现在有 `IBlockInputStream` 并且打算创建一个过滤流,那么你可以创建一个 `FilterBlockInputStream` 并用 `IBlockInputStream` 进行初始化。之后,当你从 `FilterBlockInputStream` 中拉取块时,会从你的流中提取一个块,对其进行过滤,然后将过滤后的块返回给你。查询执行流水线就是以这种方式表示的。 + +还有一些更复杂的转换。比如,当你从 `AggregatingBlockInputStream` 拉取数据时,会从数据源读取全部数据进行聚集,然后将聚集后的数据流返回给你。另一个例子:`UnionBlockInputStream` 的构造函数接受多个输入源和多个线程,其能够启动多线程从多个输入源并行读取数据。 + +> 块流使用“pull”方法来控制流:当你从第一个流中拉取块时,它会接着从嵌套的流中拉取所需的块,然后整个执行流水线开始工作。”pull“和“push”都不是最好的方案,因为控制流不是明确的,这限制了各种功能的实现,比如多个查询同步执行(多个流水线合并到一起)。这个限制可以通过协程或直接运行互相等待的线程来解决。如果控制流明确,那么我们会有更多的可能性:如果我们定位了数据从一个计算单元传递到那些外部的计算单元中其中一个计算单元的逻辑。阅读这篇[文章](http://journal.stuffwithstuff.com/2013/01/13/iteration-inside-and-out/)来获取更多的想法。 + +我们需要注意,查询执行流水线在每一步都会创建临时数据。我们要尽量使块的大小足够小,从而 CPU 缓存能够容纳下临时数据。在这个假设下,与其他计算相比,读写临时数据几乎是没有任何开销的。我们也可以考虑一种替代方案:将流水线中的多个操作融合在一起,使流水线尽可能短,并删除大量临时数据。这可能是一个优点,但同时也有缺点。比如,拆分流水线使得中间数据缓存、获取同时运行的类似查询的中间数据以及相似查询的流水线合并等功能很容易实现。 + +## 格式(Formats) + +数据格式同块流一起实现。既有仅用于向客户端输出数据的”展示“格式,如 `IBlockOutputStream` 提供的 `Pretty` 格式,也有其它输入输出格式,比如 `TabSeparated` 或 `JSONEachRow`。 + +此外还有行流:`IRowInputStream` 和 `IRowOutputStream`。它们允许你按行 pull/push 数据,而不是按块。行流只需要简单地面向行格式实现。包装器 `BlockInputStreamFromRowInputStream` 和 `BlockOutputStreamFromRowOutputStream` 允许你将面向行的流转换为正常的面向块的流。 + +## I/O + +对于面向字节的输入输出,有 `ReadBuffer` 和 `WriteBuffer` 这两个抽象类。它们用来替代 C++ 的 `iostream`。不用担心:每个成熟的 C++ 项目都会有充分的理由使用某些东西来代替 `iostream`。 + +`ReadBuffer` 和 `WriteBuffer` 由一个连续的缓冲区和指向缓冲区中某个位置的一个指针组成。实现中,缓冲区可能拥有内存,也可能不拥有内存。有一个虚方法会使用随后的数据来填充缓冲区(针对 `ReadBuffer`)或刷新缓冲区(针对 `WriteBuffer`),该虚方法很少被调用。 + +`ReadBuffer` 和 `WriteBuffer` 的实现用于处理文件、文件描述符和网络套接字(socket),也用于实现压缩(`CompressedWriteBuffer` 在写入数据前需要先用一个 `WriteBuffer` 进行初始化并进行压缩)和其它用途。`ConcatReadBuffer`、`LimitReadBuffer` 和 `HashingWriteBuffer` 的用途正如其名字所描述的一样。 + +`ReadBuffer` 和 `WriteBuffer` 仅处理字节。为了实现格式化输入和输出(比如以十进制格式写一个数字),`ReadHelpers` 和 `WriteHelpers` 头文件中有一些辅助函数可用。 + +让我们来看一下,当你把一个结果集以 `JSON` 格式写到标准输出(stdout)时会发生什么。你已经准备好从 `IBlockInputStream` 获取结果集,然后创建 `WriteBufferFromFileDescriptor(STDOUT_FILENO)` 用于写字节到标准输出,创建 `JSONRowOutputStream` 并用 `WriteBuffer` 初始化,用于将行以 `JSON` 格式写到标准输出,你还可以在其上创建 `BlockOutputStreamFromRowOutputStream`,将其表示为 `IBlockOutputStream`。然后调用 `copyData` 将数据从 `IBlockInputStream` 传输到 `IBlockOutputStream`,一切工作正常。在内部,`JSONRowOutputStream` 会写入 JSON 分隔符,并以指向 `IColumn` 的引用和行数作为参数调用 `IDataType::serializeTextJSON` 函数。随后,`IDataType::serializeTextJSON` 将会调用 `WriteHelpers.h` 中的一个方法:比如,`writeText` 用于数值类型,`writeJSONString` 用于 `DataTypeString` 。 + +## 表(Tables) + +表由 `IStorage` 接口表示。该接口的不同实现对应不同的表引擎。比如 `StorageMergeTree`、`StorageMemory` 等。这些类的实例就是表。 + +`IStorage` 中最重要的方法是 `read` 和 `write`,除此之外还有 `alter`、`rename` 和 `drop` 等方法。`read` 方法接受如下参数:需要从表中读取的列集,需要执行的 `AST` 查询,以及所需返回的流的数量。`read` 方法的返回值是一个或多个 `IBlockInputStream` 对象,以及在查询执行期间在一个表引擎内完成的关于数据处理阶段的信息。 + +在大多数情况下,`read` 方法仅负责从表中读取指定的列,而不会进行进一步的数据处理。进一步的数据处理均由查询解释器完成,不由 `IStorage` 负责。 + +但是也有值得注意的例外: + +- AST 查询被传递给 `read` 方法,表引擎可以使用它来判断是否能够使用索引,从而从表中读取更少的数据。 +- 有时候,表引擎能够将数据处理到一个特定阶段。比如,`StorageDistributed` 可以向远程服务器发送查询,要求它们将来自不同的远程服务器能够合并的数据处理到某个阶段,并返回预处理后的数据,然后查询解释器完成后续的数据处理。 + +表的 `read` 方法能够返回多个 `IBlockInputStream` 对象以允许并行处理数据。多个块输入流能够从一个表中并行读取。然后你可以通过不同的转换对这些流进行装饰(比如表达式求值或过滤),转换过程能够独立计算,并在其上创建一个 `UnionBlockInputStream`,以并行读取多个流。 + +另外也有 `TableFunction`。`TableFunction` 能够在查询的 `FROM` 字句中返回一个临时的 `IStorage` 以供使用。 + +要快速了解如何实现自己的表引擎,可以查看一些简单的表引擎,比如 `StorageMemory` 或 `StorageTinyLog`。 + +> 作为 `read` 方法的结果,`IStorage` 返回 `QueryProcessingStage` - 关于 storage 里哪部分查询已经被计算的信息。当前我们仅有非常粗粒度的信息。Storage 无法告诉我们“对于这个范围的数据,我已经处理完了 WHERE 字句里的这部分表达式”。我们需要在这个地方继续努力。 + +## 解析器(Parsers) + +查询由一个手写递归下降解析器解析。比如, `ParserSelectQuery` 只是针对查询的不同部分递归地调用下层解析器。解析器创建 `AST`。`AST` 由节点表示,节点是 `IAST` 的实例。 + +> 由于历史原因,未使用解析器生成器。 + +## 解释器(Interpreters) + +解释器负责从 `AST` 创建查询执行流水线。既有一些简单的解释器,如 `InterpreterExistsQuery` 和 `InterpreterDropQuery`,也有更复杂的解释器,如 `InterpreterSelectQuery`。查询执行流水线由块输入或输出流组成。比如,`SELECT` 查询的解释结果是从 `FROM` 字句的结果集中读取数据的 `IBlockInputStream`;`INSERT` 查询的结果是写入需要插入的数据的 `IBlockOutputStream`;`SELECT INSERT` 查询的解释结果是 `IBlockInputStream`,它在第一次读取时返回一个空结果集,同时将数据从 `SELECT` 复制到 `INSERT`。 + +`InterpreterSelectQuery` 使用 `ExpressionAnalyzer` 和 `ExpressionActions` 机制来进行查询分析和转换。这是大多数基于规则的查询优化完成的地方。`ExpressionAnalyzer` 非常混乱,应该进行重写:不同的查询转换和优化应该被提取出来并划分成不同的类,从而允许模块化转换或查询。 + +## 函数(Functions) + +函数既有普通函数,也有聚合函数。对于聚合函数,请看下一节。 + +普通函数不会改变行数 - 它们的执行看起来就像是独立地处理每一行数据。实际上,函数不会作用于一个单独的行上,而是作用在以 `Block` 为单位的数据上,以实现向量查询执行。 + +还有一些杂项函数,比如 [blockSize](../query_language/functions/other_functions.md#function-blocksize)、[rowNumberInBlock](../query_language/functions/other_functions.md#function-rownumberinblock),以及 [runningAccumulate](../query_language/functions/other_functions.md#function-runningaccumulate),它们对块进行处理,并且不遵从行的独立性。 + +ClickHouse 具有强类型,因此隐式类型转换不会发生。如果函数不支持某个特定的类型组合,则会抛出异常。但函数可以通过重载以支持许多不同的类型组合。比如,`plus` 函数(用于实现 `+` 运算符)支持任意数字类型的组合:`UInt8` + `Float32`,`UInt16` + `Int8` 等。同时,一些可变参数的函数能够级接收任意数目的参数,比如 `concat` 函数。 + +实现函数可能有些不方便,因为函数的实现需要包含所有支持该操作的数据类型和 `IColumn` 类型。比如,`plus` 函数能够利用 C++ 模板针对不同的数字类型组合、常量以及非常量的左值和右值进行代码生成。 + +> 这是一个实现动态代码生成的好地方,从而能够避免模板代码膨胀。同样,运行时代码生成也使得实现融合函数成为可能,比如融合“乘-加”,或者在单层循环迭代中进行多重比较。 + +由于向量查询执行,函数不会“短路”。比如,如果你写 `WHERE f(x) AND g(y)`,两边都会进行计算,即使是对于 `f(x)` 为 0 的行(除非 `f(x)` 是零常量表达式)。但是如果 `f(x)` 的选择条件很高,并且计算 `f(x)` 比计算 `g(y)` 要划算得多,那么最好进行多遍计算:首先计算 `f(x)`,根据计算结果对列数据进行过滤,然后计算 `g(y)`,之后只需对较小数量的数据进行过滤。 + +## 聚合函数 + +聚合函数是状态函数。它们将传入的值激活到某个状态,并允许你从该状态获取结果。聚合函数使用 `IAggregateFunction` 接口进行管理。状态可以非常简单(`AggregateFunctionCount` 的状态只是一个单一的`UInt64` 值),也可以非常复杂(`AggregateFunctionUniqCombined` 的状态是由一个线性数组、一个散列表和一个 `HyperLogLog` 概率数据结构组合而成的)。 + +为了能够在执行一个基数很大的 `GROUP BY` 查询时处理多个聚合状态,需要在 `Arena`(一个内存池)或任何合适的内存块中分配状态。状态可以有一个非平凡的构造器和析构器:比如,复杂的聚合状态能够自己分配额外的内存。这需要注意状态的创建和销毁并恰当地传递状态的所有权,以跟踪谁将何时销毁状态。 + +聚合状态可以被序列化和反序列化,以在分布式查询执行期间通过网络传递或者在内存不够的时候将其写到硬盘。聚合状态甚至可以通过 `DataTypeAggregateFunction` 存储到一个表中,以允许数据的增量聚合。 + +> 聚合函数状态的序列化数据格式目前尚未版本化。如果只是临时存储聚合状态,这样是可以的。但是我们有 `AggregatingMergeTree` 表引擎用于增量聚合,并且人们已经在生产中使用它。这就是为什么在未来当我们更改任何聚合函数的序列化格式时需要增加向后兼容的支持。 + +## 服务器(Server) + +服务器实现了多个不同的接口: + +- 一个用于任何外部客户端的 HTTP 接口。 +- 一个用于本机 ClickHouse 客户端以及在分布式查询执行中跨服务器通信的 TCP 接口。 +- 一个用于传输数据以进行拷贝的接口。 + +在内部,它只是一个没有协程、纤程等的基础多线程服务器。服务器不是为处理高速率的简单查询设计的,而是为处理相对低速率的复杂查询设计的,每一个复杂查询能够对大量的数据进行处理分析。 + +服务器使用必要的查询执行需要的环境初始化 `Context` 类:可用数据库列表、用户和访问权限、设置、集群、进程列表和查询日志等。这些环境被解释器使用。 + +我们维护了服务器 TCP 协议的完全向后向前兼容性:旧客户端可以和新服务器通信,新客户端也可以和旧服务器通信。但是我们并不想永久维护它,我们将在大约一年后删除对旧版本的支持。 + +> 对于所有的外部应用,我们推荐使用 HTTP 接口,因为该接口很简单,容易使用。TCP 接口与内部数据结构的联系更加紧密:它使用内部格式传递数据块,并使用自定义帧来压缩数据。我们没有发布该协议的 C 库,因为它需要链接大部分的 ClickHouse 代码库,这是不切实际的。 + +## 分布式查询执行 + +集群设置中的服务器大多是独立的。你可以在一个集群中的一个或多个服务器上创建一个 `Distributed` 表。`Distributed` 表本身并不存储数据,它只为集群的多个节点上的所有本地表提供一个“视图(view)”。当从 `Distributed` 表中进行 SELECT 时,它会重写该查询,根据负载平衡设置来选择远程节点,并将查询发送给节点。`Distributed` 表请求远程服务器处理查询,直到可以合并来自不同服务器的中间结果的阶段。然后它接收中间结果并进行合并。分布式表会尝试将尽可能多的工作分配给远程服务器,并且不会通过网络发送太多的中间数据。 + +> 当 `IN` 或 `JOIN` 子句中包含子查询并且每个子查询都使用分布式表时,事情会变得更加复杂。我们有不同的策略来执行这些查询。 + +分布式查询执行没有全局查询计划。每个节点都有针对自己的工作部分的本地查询计划。我们仅有简单的一次性分布式查询执行:将查询发送给远程节点,然后合并结果。但是对于具有高基数的 `GROUP BY` 或具有大量临时数据的 `JOIN` 这样困难的查询的来说,这是不可行的:在这种情况下,我们需要在服务器之间“改组”数据,这需要额外的协调。ClickHouse 不支持这类查询执行,我们需要在这方面进行努力。 + +## Merge Tree + +`MergeTree` 是一系列支持按主键索引的存储引擎。主键可以是一个任意的列或表达式的元组。`MergeTree` 表中的数据存储于“分块”中。每一个分块以主键序存储数据(数据按主键元组的字典序排序)。表的所有列都存储在这些“分块”中分离的 `column.bin` 文件中。`column.bin` 文件由压缩块组成,每一个块通常是 64 KB 到 1 MB 大小的未压缩数据,具体取决于平均值大小。这些块由一个接一个连续放置的列值组成。每一列的列值顺序相同(顺序由主键定义),因此当你按多列进行迭代时,你能够得到相应列的值。 + +主键本身是“稀疏”的。它并不是索引单一的行,而是索引某个范围内的数据。一个单独的 `primary.idx` 文件具有每个第 N 行的主键值,其中 N 称为 `index_granularity`(通常,N = 8192)。同时,对于每一列,都有带有标记的 `column.mrk` 文件,该文件记录的是每个第 N 行在数据文件中的偏移量。每个标记是一个 pair:文件中的偏移量到压缩块的起始,以及解压缩块中的偏移量到数据的起始。通常,压缩块根据标记对齐,并且解压缩块中的偏移量为 0。`primary.idx` 的数据始终驻留在内存,同时 `column.mrk` 的数据被缓存。 + +当我们要从 `MergeTree` 的一个分块中读取部分内容时,我们会查看 `primary.idx` 数据并查找可能包含所请求数据的范围,然后查看 `column.mrk` 并计算偏移量从而得知从哪里开始读取些范围的数据。由于稀疏性,可能会读取额外的数据。ClickHouse 不适用于高负载的简单点查询,因为对于每一个键,整个 `index_granularity` 范围的行的数据都需要读取,并且对于每一列需要解压缩整个压缩块。我们使索引稀疏,是因为每一个单一的服务器需要在索引没有明显内存消耗的情况下,维护数万亿行的数据。另外,由于主键是稀疏的,导致其不是唯一的:无法在 INSERT 时检查一个键在表中是否存在。你可以在一个表中使用同一个键创建多个行。 + +当你向 `MergeTree` 中插入一堆数据时,数据按主键排序并形成一个新的分块。为了保证分块的数量相对较少,有后台线程定期选择一些分块并将它们合并成一个有序的分块,这就是 `MergeTree` 的名称来源。当然,合并会导致“写入放大”。所有的分块都是不可变的:它们仅会被创建和删除,不会被修改。当运行 `SELECT` 查询时,`MergeTree` 会保存一个表的快照(分块集合)。合并之后,还会保留旧的分块一段时间,以便发生故障后更容易恢复,因此如果我们发现某些合并后的分块可能已损坏,我们可以将其替换为原分块。 + +`MergeTree` 不是 LSM 树,因为它不包含”memtable“和”log“:插入的数据直接写入文件系统。这使得它仅适用于批量插入数据,而不适用于非常频繁地一行一行插入 - 大约每秒一次是没问题的,但是每秒一千次就会有问题。我们这样做是为了简单起见,因为我们已经在我们的应用中批量插入数据。 + +> `MergeTree` 表只能有一个(主)索引:没有任何辅助索引。在一个逻辑表下,允许有多个物理表示,比如,可以以多个物理顺序存储数据,或者同时表示预聚合数据和原始数据。 + +有些 `MergeTree` 引擎会在后台合并期间做一些额外工作,比如 `CollapsingMergeTree` 和 `AggregatingMergeTree`。这可以视为对更新的特殊支持。请记住这些不是真正的更新,因为用户通常无法控制后台合并将会执行的时间,并且 `MergeTree` 中的数据几乎总是存储在多个分块中,而不是完全合并的形式。 + +## 复制(Replication) + +ClickHouse 中的复制是基于表实现的。你可以在同一个服务器上有一些可复制的表和不可复制的表。你也可以以不同的方式进行表的复制,比如一个表进行双因子复制,另一个进行三因子复制。 + +复制是在 `ReplicatedMergeTree` 存储引擎中实现的。`ZooKeeper` 中的路径被指定为存储引擎的参数。`ZooKeeper` 中所有具有相同路径的表互为副本:它们同步数据并保持一致性。只需创建或删除表,就可以实现动态添加或删除副本。 + +复制使用异步多主机方案。你可以将数据插入到与 `ZooKeeper` 进行会话的任意副本中,并将数据复制到所有其它副本中。由于 ClickHouse 不支持 UPDATEs,因此复制是无冲突的。由于没有对插入的仲裁确认,如果一个节点发生故障,刚刚插入的数据可能会丢失。 + +用于复制的元数据存储在 ZooKeeper 中。其中一个复制日志列出了要执行的操作。操作包括:获取分块、合并分块和删除分区等。每一个副本将复制日志复制到其队列中,然后执行队列中的操作。比如,在插入时,在复制日志中创建“获取分块”这一操作,然后每一个副本都会去下载该分块。所有副本之间会协调进行合并以获得相同字节的结果。所有的分块在所有的副本上以相同的方式合并。为实现该目的,其中一个副本被选为领导者,该副本首先进行合并,并把“合并分块”操作写到日志中。 + +复制是物理的:只有压缩的分块会在节点之间传输,查询则不会。为了降低网络成本(避免网络放大),大多数情况下,会在每一个副本上独立地处理合并。只有在存在显著的合并延迟的情况下,才会通过网络发送大块的合并分块。 + +另外,每一个副本将其状态作为分块和校验和组成的集合存储在 ZooKeeper 中。当本地文件系统中的状态与 ZooKeeper 中引用的状态不同时,该副本会通过从其它副本下载缺失和损坏的分块来恢复其一致性。当本地文件系统中出现一些意外或损坏的数据时,ClickHouse 不会将其删除,而是将其移动到一个单独的目录下并忘记它。 + +> ClickHouse 集群由独立的分片组成,每一个分片由多个副本组成。集群不是弹性的,因此在添加新的分片后,数据不会自动在分片之间重新平衡。相反,集群负载将变得不均衡。该实现为你提供了更多控制,对于相对较小的集群,例如只有数十个节点的集群来说是很好的。但是对于我们在生产中使用的具有数百个节点的集群来说,这种方法成为一个重大缺陷。我们应该实现一个表引擎,使得该引擎能够跨集群扩展数据,同时具有动态复制的区域,这些区域能够在集群之间自动拆分和平衡。 + +[来源文章](https://clickhouse.yandex/docs/en/development/architecture/) diff --git a/docs/zh/operations/settings/settings_users.md b/docs/zh/operations/settings/settings_users.md new file mode 120000 index 00000000000..3a6a7cf6948 --- /dev/null +++ b/docs/zh/operations/settings/settings_users.md @@ -0,0 +1 @@ +../../../en/operations/settings/settings_users.md \ No newline at end of file diff --git a/docs/zh/query_language/system.md b/docs/zh/query_language/system.md new file mode 120000 index 00000000000..6061858c3f2 --- /dev/null +++ b/docs/zh/query_language/system.md @@ -0,0 +1 @@ +../../en/query_language/system.md \ No newline at end of file diff --git a/libs/libcommon/CMakeLists.txt b/libs/libcommon/CMakeLists.txt index 6644e2f527e..1e3be7f61d6 100644 --- a/libs/libcommon/CMakeLists.txt +++ b/libs/libcommon/CMakeLists.txt @@ -22,7 +22,10 @@ add_library(common src/setTerminalEcho.cpp src/getThreadNumber.cpp src/argsToConfig.cpp + src/StackTrace.cpp + include/common/SimpleCache.h + include/common/StackTrace.h include/common/Types.h include/common/DayNum.h include/common/DateLUT.h @@ -59,6 +62,14 @@ add_library(common ${CONFIG_COMMON} ) +if (USE_UNWIND) + target_compile_definitions (common PRIVATE USE_UNWIND=1) + target_include_directories (common BEFORE PRIVATE ${UNWIND_INCLUDE_DIR}) + if (NOT USE_INTERNAL_UNWIND_LIBRARY_FOR_EXCEPTION_HANDLING) + target_link_libraries (common PRIVATE ${UNWIND_LIBRARY}) + endif () +endif () + # When testing for memory leaks with Valgrind, dont link tcmalloc or jemalloc. if (USE_JEMALLOC) diff --git a/libs/libcommon/include/common/DateLUTImpl.h b/libs/libcommon/include/common/DateLUTImpl.h index 28d536fc93d..344d363b0d7 100644 --- a/libs/libcommon/include/common/DateLUTImpl.h +++ b/libs/libcommon/include/common/DateLUTImpl.h @@ -20,6 +20,16 @@ #endif #endif +/// Flags for toYearWeek() function. +enum class WeekModeFlag : UInt8 +{ + MONDAY_FIRST = 1, + YEAR = 2, + FIRST_WEEKDAY = 4, + NEWYEAR_DAY = 8 +}; +typedef std::pair YearWeek; + /** Lookup table to conversion of time to date, and to month / year / day of week / day of month and so on. * First time was implemented for OLAPServer, that needed to do billions of such transformations. */ @@ -379,6 +389,167 @@ public: return toISOWeek(toDayNum(t)); } + /* + The bits in week_mode has the following meaning: + WeekModeFlag::MONDAY_FIRST (0) If not set Sunday is first day of week + If set Monday is first day of week + WeekModeFlag::YEAR (1) If not set Week is in range 0-53 + + Week 0 is returned for the the last week of the previous year (for + a date at start of january) In this case one can get 53 for the + first week of next year. This flag ensures that the week is + relevant for the given year. Note that this flag is only + releveant if WeekModeFlag::JANUARY is not set. + + If set Week is in range 1-53. + + In this case one may get week 53 for a date in January (when + the week is that last week of previous year) and week 1 for a + date in December. + + WeekModeFlag::FIRST_WEEKDAY (2) If not set Weeks are numbered according + to ISO 8601:1988 + If set The week that contains the first + 'first-day-of-week' is week 1. + + WeekModeFlag::NEWYEAR_DAY (3) If not set no meaning + If set The week that contains the January 1 is week 1. + Week is in range 1-53. + And ignore WeekModeFlag::YEAR, WeekModeFlag::FIRST_WEEKDAY + + ISO 8601:1988 means that if the week containing January 1 has + four or more days in the new year, then it is week 1; + Otherwise it is the last week of the previous year, and the + next week is week 1. + */ + inline YearWeek toYearWeek(DayNum d, UInt8 week_mode) const + { + bool newyear_day_mode = week_mode & static_cast(WeekModeFlag::NEWYEAR_DAY); + week_mode = check_week_mode(week_mode); + bool monday_first_mode = week_mode & static_cast(WeekModeFlag::MONDAY_FIRST); + bool week_year_mode = week_mode & static_cast(WeekModeFlag::YEAR); + bool first_weekday_mode = week_mode & static_cast(WeekModeFlag::FIRST_WEEKDAY); + + // Calculate week number of WeekModeFlag::NEWYEAR_DAY mode + if (newyear_day_mode) + { + return toYearWeekOfNewyearMode(d, monday_first_mode); + } + + YearWeek yw(toYear(d), 0); + UInt16 days = 0; + UInt16 daynr = makeDayNum(yw.first, toMonth(d), toDayOfMonth(d)); + UInt16 first_daynr = makeDayNum(yw.first, 1, 1); + + // 0 for monday, 1 for tuesday ... + // get weekday from first day in year. + UInt16 weekday = calc_weekday(DayNum(first_daynr), !monday_first_mode); + + if (toMonth(d) == 1 && toDayOfMonth(d) <= static_cast(7 - weekday)) + { + if (!week_year_mode && ((first_weekday_mode && weekday != 0) || (!first_weekday_mode && weekday >= 4))) + return yw; + week_year_mode = 1; + (yw.first)--; + first_daynr -= (days = calc_days_in_year(yw.first)); + weekday = (weekday + 53 * 7 - days) % 7; + } + + if ((first_weekday_mode && weekday != 0) || (!first_weekday_mode && weekday >= 4)) + days = daynr - (first_daynr + (7 - weekday)); + else + days = daynr - (first_daynr - weekday); + + if (week_year_mode && days >= 52 * 7) + { + weekday = (weekday + calc_days_in_year(yw.first)) % 7; + if ((!first_weekday_mode && weekday < 4) || (first_weekday_mode && weekday == 0)) + { + (yw.first)++; + yw.second = 1; + return yw; + } + } + yw.second = days / 7 + 1; + return yw; + } + + /// Calculate week number of WeekModeFlag::NEWYEAR_DAY mode + /// The week number 1 is the first week in year that contains January 1, + inline YearWeek toYearWeekOfNewyearMode(DayNum d, bool monday_first_mode) const + { + YearWeek yw(0, 0); + UInt16 offset_day = monday_first_mode ? 0U : 1U; + + // Checking the week across the year + yw.first = toYear(DayNum(d + 7 - toDayOfWeek(DayNum(d + offset_day)))); + + DayNum first_day = makeDayNum(yw.first, 1, 1); + DayNum this_day = d; + + if (monday_first_mode) + { + // Rounds down a date to the nearest Monday. + first_day = toFirstDayNumOfWeek(first_day); + this_day = toFirstDayNumOfWeek(d); + } + else + { + // Rounds down a date to the nearest Sunday. + if (toDayOfWeek(first_day) != 7) + first_day = DayNum(first_day - toDayOfWeek(first_day)); + if (toDayOfWeek(d) != 7) + this_day = DayNum(d - toDayOfWeek(d)); + } + yw.second = (this_day - first_day) / 7 + 1; + return yw; + } + + /** + * get first day of week with week_mode, return Sunday or Monday + */ + inline DayNum toFirstDayNumOfWeek(DayNum d, UInt8 week_mode) const + { + bool monday_first_mode = week_mode & static_cast(WeekModeFlag::MONDAY_FIRST); + if (monday_first_mode) + { + return toFirstDayNumOfWeek(d); + } + else + { + return (toDayOfWeek(d) != 7) ? DayNum(d - toDayOfWeek(d)) : d; + } + } + + /* + * check and change mode to effective + */ + inline UInt8 check_week_mode(UInt8 mode) const + { + UInt8 week_format = (mode & 7); + if (!(week_format & static_cast(WeekModeFlag::MONDAY_FIRST))) + week_format ^= static_cast(WeekModeFlag::FIRST_WEEKDAY); + return week_format; + } + + /* + * Calc weekday from d + * Returns 0 for monday, 1 for tuesday ... + */ + inline unsigned calc_weekday(DayNum d, bool sunday_first_day_of_week) const + { + if (!sunday_first_day_of_week) + return toDayOfWeek(d) - 1; + else + return toDayOfWeek(DayNum(d + 1)) - 1; + } + + /* Calc days in one year. */ + inline unsigned calc_days_in_year(UInt16 year) const + { + return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)) ? 366 : 365); + } + /// Number of month from some fixed moment in the past (year * 12 + month) inline unsigned toRelativeMonthNum(DayNum d) const { diff --git a/libs/libcommon/include/common/JSON.h b/libs/libcommon/include/common/JSON.h index 9bb109a840f..5f3d9325626 100644 --- a/libs/libcommon/include/common/JSON.h +++ b/libs/libcommon/include/common/JSON.h @@ -60,7 +60,18 @@ public: checkInit(); } - JSON(const JSON & rhs) : ptr_begin(rhs.ptr_begin), ptr_end(rhs.ptr_end), level(rhs.level) {} + JSON(const JSON & rhs) + { + *this = rhs; + } + + JSON & operator=(const JSON & rhs) + { + ptr_begin = rhs.ptr_begin; + ptr_end = rhs.ptr_end; + level = rhs.level; + return *this; + } const char * data() const { return ptr_begin; } const char * dataEnd() const { return ptr_end; } diff --git a/dbms/src/Common/SimpleCache.h b/libs/libcommon/include/common/SimpleCache.h similarity index 80% rename from dbms/src/Common/SimpleCache.h rename to libs/libcommon/include/common/SimpleCache.h index 06d29c8ba7a..2cf4348d0d7 100644 --- a/dbms/src/Common/SimpleCache.h +++ b/libs/libcommon/include/common/SimpleCache.h @@ -9,6 +9,7 @@ /** The simplest cache for a free function. * You can also pass a static class method or lambda without captures. * The size is unlimited. Values are stored permanently and never evicted. + * But single record or all cache can be manually dropped. * Mutex is used for synchronization. * Suitable only for the simplest cases. * @@ -53,6 +54,18 @@ public: return res; } + template + void update(Args &&... args) + { + Result res = f(std::forward(args)...); + { + std::lock_guard lock(mutex); + + Key key{std::forward(args)...}; + cache[key] = std::move(res); + } + } + void drop() { std::lock_guard lock(mutex); diff --git a/libs/libcommon/include/common/StackTrace.h b/libs/libcommon/include/common/StackTrace.h new file mode 100644 index 00000000000..9c27ffdcc65 --- /dev/null +++ b/libs/libcommon/include/common/StackTrace.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include +#include +#include + +#ifdef __APPLE__ +// ucontext is not available without _XOPEN_SOURCE +#define _XOPEN_SOURCE 700 +#endif +#include + +struct NoCapture +{ +}; + +/// Tries to capture current stack trace using libunwind or signal context +/// NOTE: All StackTrace constructors are signal safe +class StackTrace +{ +public: + static constexpr size_t capacity = 32; + using Frames = std::array; + + /// Tries to capture stack trace + StackTrace(); + + /// Tries to capture stack trace. Fallbacks on parsing caller address from + /// signal context if no stack trace could be captured + StackTrace(const ucontext_t & signal_context); + + /// Creates empty object for deferred initialization + StackTrace(NoCapture); + + /// Fills stack trace frames with provided sequence + StackTrace(const std::vector & source_frames); + + size_t getSize() const; + const Frames & getFrames() const; + std::string toString() const; + +protected: + void tryCapture(); + static std::string toStringImpl(const Frames & frames, size_t size); + + size_t size = 0; + Frames frames; +}; + +std::string signalToErrorMessage(int sig, const siginfo_t & info, const ucontext_t & context); + +void * getCallerAddress(const ucontext_t & context); diff --git a/libs/libcommon/include/common/StringRef.h b/libs/libcommon/include/common/StringRef.h index 8d0ed7195a8..f0c413f70fe 100644 --- a/libs/libcommon/include/common/StringRef.h +++ b/libs/libcommon/include/common/StringRef.h @@ -288,7 +288,7 @@ namespace std namespace ZeroTraits { - inline bool check(StringRef x) { return 0 == x.size; } + inline bool check(const StringRef & x) { return 0 == x.size; } inline void set(StringRef & x) { x.size = 0; } } diff --git a/libs/libcommon/include/common/unaligned.h b/libs/libcommon/include/common/unaligned.h index 2b1505ba2d3..ca73298adfb 100644 --- a/libs/libcommon/include/common/unaligned.h +++ b/libs/libcommon/include/common/unaligned.h @@ -1,6 +1,7 @@ #pragma once #include +#include template @@ -11,8 +12,14 @@ inline T unalignedLoad(const void * address) return res; } +/// We've had troubles before with wrong store size due to integral promotions +/// (e.g., unalignedStore(dest, uint16_t + uint16_t) stores an uint32_t). +/// To prevent this, make the caller specify the stored type explicitly. +/// To disable deduction of T, wrap the argument type with std::enable_if. template -inline void unalignedStore(void * address, const T & src) +inline void unalignedStore(void * address, + const typename std::enable_if::type & src) { + static_assert(std::is_trivially_copyable_v); memcpy(address, &src, sizeof(src)); } diff --git a/libs/libcommon/src/DateLUT.cpp b/libs/libcommon/src/DateLUT.cpp index 66ca8e6d201..ce3e7e32a26 100644 --- a/libs/libcommon/src/DateLUT.cpp +++ b/libs/libcommon/src/DateLUT.cpp @@ -6,6 +6,7 @@ #include #include + namespace { @@ -13,15 +14,16 @@ Poco::DigestEngine::Digest calcSHA1(const std::string & path) { std::ifstream stream(path); if (!stream) - throw Poco::Exception("Error while opening file: `" + path + "'."); + throw Poco::Exception("Error while opening file: '" + path + "'."); Poco::SHA1Engine digest_engine; Poco::DigestInputStream digest_stream(digest_engine, stream); digest_stream.ignore(std::numeric_limits::max()); if (!stream.eof()) - throw Poco::Exception("Error while reading file: `" + path + "'."); + throw Poco::Exception("Error while reading file: '" + path + "'."); return digest_engine.digest(); } + std::string determineDefaultTimeZone() { namespace fs = boost::filesystem; @@ -39,7 +41,7 @@ std::string determineDefaultTimeZone() if (tz_env_var) { - error_prefix = std::string("Could not determine time zone from TZ variable value: `") + tz_env_var + "': "; + error_prefix = std::string("Could not determine time zone from TZ variable value: '") + tz_env_var + "': "; if (*tz_env_var == ':') ++tz_env_var; @@ -50,22 +52,50 @@ std::string determineDefaultTimeZone() else { error_prefix = "Could not determine local time zone: "; - tz_file_path = "/etc/localtime"; /// FIXME: in case of no TZ use the immediate linked file as tz name. + tz_file_path = "/etc/localtime"; + + /// No TZ variable and no tzdata installed (e.g. Docker) + if (!fs::exists(tz_file_path)) + return "UTC"; + + /// Read symlink but not transitive. + /// Example: + /// /etc/localtime -> /usr/share/zoneinfo//UTC + /// /usr/share/zoneinfo//UTC -> UCT + /// But the preferred time zone name is pointed by the first link (UTC), and the second link is just an internal detail. + if (fs::is_symlink(tz_file_path)) + { + tz_file_path = fs::read_symlink(tz_file_path); + /// If it's relative - make it absolute. + if (tz_file_path.is_relative()) + tz_file_path = (fs::path("/etc/") / tz_file_path).lexically_normal(); + } } try { tz_database_path = fs::canonical(tz_database_path); - tz_file_path = fs::canonical(tz_file_path, tz_database_path); /// The tzdata file exists. If it is inside the tz_database_dir, /// then the relative path is the time zone id. - fs::path relative_path = tz_file_path.lexically_relative(tz_database_path); - if (!relative_path.empty() && *relative_path.begin() != ".." && *relative_path.begin() != ".") - return tz_name.empty() ? relative_path.string() : tz_name; + { + fs::path relative_path = tz_file_path.lexically_relative(tz_database_path); - /// The file is not inside the tz_database_dir, so we hope that it was copied and - /// try to find the file with exact same contents in the database. + if (!relative_path.empty() && *relative_path.begin() != ".." && *relative_path.begin() != ".") + return tz_name.empty() ? relative_path.string() : tz_name; + } + + /// Try the same with full symlinks resolution + { + tz_file_path = fs::canonical(tz_file_path, tz_database_path); + + fs::path relative_path = tz_file_path.lexically_relative(tz_database_path); + if (!relative_path.empty() && *relative_path.begin() != ".." && *relative_path.begin() != ".") + return tz_name.empty() ? relative_path.string() : tz_name; + } + + /// The file is not inside the tz_database_dir, so we hope that it was copied (not symlinked) + /// and try to find the file with exact same contents in the database. size_t tzfile_size = fs::file_size(tz_file_path); Poco::SHA1Engine::Digest tzfile_sha1 = calcSHA1(tz_file_path.string()); diff --git a/libs/libcommon/src/StackTrace.cpp b/libs/libcommon/src/StackTrace.cpp new file mode 100644 index 00000000000..ea60626edf0 --- /dev/null +++ b/libs/libcommon/src/StackTrace.cpp @@ -0,0 +1,282 @@ +#include +#include +#include + +#include +#include +#include +#include + +#if USE_UNWIND +#define UNW_LOCAL_ONLY +#include +#endif + +std::string signalToErrorMessage(int sig, const siginfo_t & info, const ucontext_t & context) +{ + std::stringstream error; + switch (sig) + { + case SIGSEGV: + { + /// Print info about address and reason. + if (nullptr == info.si_addr) + error << "Address: NULL pointer."; + else + error << "Address: " << info.si_addr; + +#if defined(__x86_64__) && !defined(__FreeBSD__) && !defined(__APPLE__) + auto err_mask = context.uc_mcontext.gregs[REG_ERR]; + if ((err_mask & 0x02)) + error << " Access: write."; + else + error << " Access: read."; +#endif + + switch (info.si_code) + { + case SEGV_ACCERR: + error << " Attempted access has violated the permissions assigned to the memory area."; + break; + case SEGV_MAPERR: + error << " Address not mapped to object."; + break; + default: + error << " Unknown si_code."; + break; + } + break; + } + + case SIGBUS: + { + switch (info.si_code) + { + case BUS_ADRALN: + error << "Invalid address alignment."; + break; + case BUS_ADRERR: + error << "Non-existant physical address."; + break; + case BUS_OBJERR: + error << "Object specific hardware error."; + break; + + // Linux specific +#if defined(BUS_MCEERR_AR) + case BUS_MCEERR_AR: + error << "Hardware memory error: action required."; + break; +#endif +#if defined(BUS_MCEERR_AO) + case BUS_MCEERR_AO: + error << "Hardware memory error: action optional."; + break; +#endif + + default: + error << "Unknown si_code."; + break; + } + break; + } + + case SIGILL: + { + switch (info.si_code) + { + case ILL_ILLOPC: + error << "Illegal opcode."; + break; + case ILL_ILLOPN: + error << "Illegal operand."; + break; + case ILL_ILLADR: + error << "Illegal addressing mode."; + break; + case ILL_ILLTRP: + error << "Illegal trap."; + break; + case ILL_PRVOPC: + error << "Privileged opcode."; + break; + case ILL_PRVREG: + error << "Privileged register."; + break; + case ILL_COPROC: + error << "Coprocessor error."; + break; + case ILL_BADSTK: + error << "Internal stack error."; + break; + default: + error << "Unknown si_code."; + break; + } + break; + } + + case SIGFPE: + { + switch (info.si_code) + { + case FPE_INTDIV: + error << "Integer divide by zero."; + break; + case FPE_INTOVF: + error << "Integer overflow."; + break; + case FPE_FLTDIV: + error << "Floating point divide by zero."; + break; + case FPE_FLTOVF: + error << "Floating point overflow."; + break; + case FPE_FLTUND: + error << "Floating point underflow."; + break; + case FPE_FLTRES: + error << "Floating point inexact result."; + break; + case FPE_FLTINV: + error << "Floating point invalid operation."; + break; + case FPE_FLTSUB: + error << "Subscript out of range."; + break; + default: + error << "Unknown si_code."; + break; + } + break; + } + } + + return error.str(); +} + +void * getCallerAddress(const ucontext_t & context) +{ +#if defined(__x86_64__) + /// Get the address at the time the signal was raised from the RIP (x86-64) +#if defined(__FreeBSD__) + return reinterpret_cast(context.uc_mcontext.mc_rip); +#elif defined(__APPLE__) + return reinterpret_cast(context.uc_mcontext->__ss.__rip); +#else + return reinterpret_cast(context.uc_mcontext.gregs[REG_RIP]); +#endif +#elif defined(__aarch64__) + return reinterpret_cast(context.uc_mcontext.pc); +#endif + + return nullptr; +} + +StackTrace::StackTrace() +{ + tryCapture(); +} + +StackTrace::StackTrace(const ucontext_t & signal_context) +{ + tryCapture(); + + if (size == 0) + { + /// No stack trace was captured. At least we can try parsing caller address + void * caller_address = getCallerAddress(signal_context); + if (caller_address) + frames[size++] = reinterpret_cast(caller_address); + } +} + +StackTrace::StackTrace(NoCapture) +{ +} + +StackTrace::StackTrace(const std::vector & source_frames) +{ + for (size = 0; size < std::min(source_frames.size(), capacity); ++size) + frames[size] = source_frames[size]; +} + +void StackTrace::tryCapture() +{ + size = 0; +#if USE_UNWIND + size = unw_backtrace(frames.data(), capacity); +#endif +} + +size_t StackTrace::getSize() const +{ + return size; +} + +const StackTrace::Frames& StackTrace::getFrames() const +{ + return frames; +} + +std::string StackTrace::toString() const +{ + /// Calculation of stack trace text is extremely slow. + /// We use simple cache because otherwise the server could be overloaded by trash queries. + + static SimpleCache func_cached; + return func_cached(frames, size); +} + +std::string StackTrace::toStringImpl(const Frames & frames, size_t size) +{ + if (size == 0) + return ""; + + char ** symbols = backtrace_symbols(frames.data(), size); + if (!symbols) + return ""; + + std::stringstream backtrace; + try + { + for (size_t i = 0; i < size; i++) + { + /// We do "demangling" of names. The name is in parenthesis, before the '+' character. + + char * name_start = nullptr; + char * name_end = nullptr; + std::string demangled_name; + int status = 0; + + if (nullptr != (name_start = strchr(symbols[i], '(')) + && nullptr != (name_end = strchr(name_start, '+'))) + { + ++name_start; + *name_end = '\0'; + demangled_name = demangle(name_start, status); + *name_end = '+'; + } + + backtrace << i << ". "; + + if (0 == status && name_start && name_end) + { + backtrace.write(symbols[i], name_start - symbols[i]); + backtrace << demangled_name << name_end; + } + else + backtrace << symbols[i]; + + backtrace << std::endl; + } + } + catch (...) + { + free(symbols); + throw; + } + + free(symbols); + return backtrace.str(); +} diff --git a/libs/libcommon/src/demangle.cpp b/libs/libcommon/src/demangle.cpp index eab8a55abe0..e65ead7524b 100644 --- a/libs/libcommon/src/demangle.cpp +++ b/libs/libcommon/src/demangle.cpp @@ -1,6 +1,14 @@ #include -#if _MSC_VER +#if defined(__has_feature) + #if __has_feature(memory_sanitizer) + #define MEMORY_SANITIZER 1 + #endif +#elif defined(__MEMORY_SANITIZER__) + #define MEMORY_SANITIZER 1 +#endif + +#if _MSC_VER || MEMORY_SANITIZER std::string demangle(const char * name, int & status) { diff --git a/libs/libdaemon/CMakeLists.txt b/libs/libdaemon/CMakeLists.txt index d74a78fff31..e7207cb7e85 100644 --- a/libs/libdaemon/CMakeLists.txt +++ b/libs/libdaemon/CMakeLists.txt @@ -6,12 +6,6 @@ add_library (daemon include/daemon/GraphiteWriter.h ) -if (USE_UNWIND) - target_compile_definitions (daemon PRIVATE USE_UNWIND=1) - target_include_directories (daemon BEFORE PRIVATE ${UNWIND_INCLUDE_DIR}) - target_link_libraries (daemon PRIVATE ${UNWIND_LIBRARY}) -endif () - target_include_directories (daemon PUBLIC include) target_link_libraries (daemon PUBLIC loggers PRIVATE clickhouse_common_io clickhouse_common_config common ${Poco_Net_LIBRARY} ${Poco_Util_LIBRARY} ${EXECINFO_LIBRARIES}) diff --git a/libs/libdaemon/src/BaseDaemon.cpp b/libs/libdaemon/src/BaseDaemon.cpp index 596b738c0bb..b40f00a700f 100644 --- a/libs/libdaemon/src/BaseDaemon.cpp +++ b/libs/libdaemon/src/BaseDaemon.cpp @@ -11,9 +11,11 @@ #include #include #include + #include #include #include +#include #include #include #include @@ -44,14 +46,9 @@ #include #include -#if USE_UNWIND - #define UNW_LOCAL_ONLY - #include -#endif - #ifdef __APPLE__ // ucontext is not available without _XOPEN_SOURCE -#define _XOPEN_SOURCE +#define _XOPEN_SOURCE 700 #endif #include @@ -119,7 +116,7 @@ static void call_default_signal_handler(int sig) using ThreadNumber = decltype(getThreadNumber()); -static const size_t buf_size = sizeof(int) + sizeof(siginfo_t) + sizeof(ucontext_t) + sizeof(ThreadNumber); +static const size_t buf_size = sizeof(int) + sizeof(siginfo_t) + sizeof(ucontext_t) + sizeof(StackTrace) + sizeof(ThreadNumber); using signal_function = void(int, siginfo_t*, void*); @@ -156,9 +153,13 @@ static void faultSignalHandler(int sig, siginfo_t * info, void * context) char buf[buf_size]; DB::WriteBufferFromFileDescriptor out(signal_pipe.write_fd, buf_size, buf); + const ucontext_t signal_context = *reinterpret_cast(context); + const StackTrace stack_trace(signal_context); + DB::writeBinary(sig, out); DB::writePODBinary(*info, out); - DB::writePODBinary(*reinterpret_cast(context), out); + DB::writePODBinary(signal_context, out); + DB::writePODBinary(stack_trace, out); DB::writeBinary(getThreadNumber(), out); out.next(); @@ -170,46 +171,6 @@ static void faultSignalHandler(int sig, siginfo_t * info, void * context) } -#if USE_UNWIND -/** We suppress the following ASan report. Also shown by Valgrind. -==124==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7f054be57000 at pc 0x0000068b0649 bp 0x7f060eeac590 sp 0x7f060eeabd40 -READ of size 1 at 0x7f054be57000 thread T3 - #0 0x68b0648 in write (/usr/bin/clickhouse+0x68b0648) - #1 0x717da02 in write_validate /build/obj-x86_64-linux-gnu/../contrib/libunwind/src/x86_64/Ginit.c:110:13 - #2 0x717da02 in mincore_validate /build/obj-x86_64-linux-gnu/../contrib/libunwind/src/x86_64/Ginit.c:146 - #3 0x717dec1 in validate_mem /build/obj-x86_64-linux-gnu/../contrib/libunwind/src/x86_64/Ginit.c:206:7 - #4 0x717dec1 in access_mem /build/obj-x86_64-linux-gnu/../contrib/libunwind/src/x86_64/Ginit.c:240 - #5 0x71881a9 in dwarf_get /build/obj-x86_64-linux-gnu/../contrib/libunwind/include/tdep-x86_64/libunwind_i.h:168:12 - #6 0x71881a9 in apply_reg_state /build/obj-x86_64-linux-gnu/../contrib/libunwind/src/dwarf/Gparser.c:872 - #7 0x718705c in _ULx86_64_dwarf_step /build/obj-x86_64-linux-gnu/../contrib/libunwind/src/dwarf/Gparser.c:953:10 - #8 0x718f155 in _ULx86_64_step /build/obj-x86_64-linux-gnu/../contrib/libunwind/src/x86_64/Gstep.c:71:9 - #9 0x7162671 in backtraceLibUnwind(void**, unsigned long, ucontext_t&) /build/obj-x86_64-linux-gnu/../libs/libdaemon/src/BaseDaemon.cpp:202:14 - */ -size_t NO_SANITIZE_ADDRESS backtraceLibUnwind(void ** out_frames, size_t max_frames, ucontext_t & context) -{ - unw_cursor_t cursor; - - if (unw_init_local2(&cursor, &context, UNW_INIT_SIGNAL_FRAME) < 0) - return 0; - - size_t i = 0; - for (; i < max_frames; ++i) - { - unw_word_t ip; - unw_get_reg(&cursor, UNW_REG_IP, &ip); - out_frames[i] = reinterpret_cast(ip); - - /// NOTE This triggers "AddressSanitizer: stack-buffer-overflow". Looks like false positive. - /// It's Ok, because we use this method if the program is crashed nevertheless. - if (!unw_step(&cursor)) - break; - } - - return i; -} -#endif - - /** The thread that read info about signal or std::terminate from pipe. * On HUP / USR1, close log files (for new files to be opened later). * On information about std::terminate, write it to log. @@ -271,13 +232,15 @@ public: { siginfo_t info; ucontext_t context; + StackTrace stack_trace(NoCapture{}); ThreadNumber thread_num; DB::readPODBinary(info, in); DB::readPODBinary(context, in); + DB::readPODBinary(stack_trace, in); DB::readBinary(thread_num, in); - onFault(sig, info, context, thread_num); + onFault(sig, info, context, stack_trace, thread_num); } } } @@ -292,224 +255,14 @@ private: LOG_ERROR(log, "(version " << VERSION_STRING << VERSION_OFFICIAL << ") (from thread " << thread_num << ") " << message); } - void onFault(int sig, siginfo_t & info, ucontext_t & context, ThreadNumber thread_num) const + void onFault(int sig, siginfo_t & info, ucontext_t & context, const StackTrace & stack_trace, ThreadNumber thread_num) const { LOG_ERROR(log, "########################################"); LOG_ERROR(log, "(version " << VERSION_STRING << VERSION_OFFICIAL << ") (from thread " << thread_num << ") " << "Received signal " << strsignal(sig) << " (" << sig << ")" << "."); - void * caller_address = nullptr; - -#if defined(__x86_64__) - /// Get the address at the time the signal was raised from the RIP (x86-64) - #if defined(__FreeBSD__) - caller_address = reinterpret_cast(context.uc_mcontext.mc_rip); - #elif defined(__APPLE__) - caller_address = reinterpret_cast(context.uc_mcontext->__ss.__rip); - #else - caller_address = reinterpret_cast(context.uc_mcontext.gregs[REG_RIP]); - auto err_mask = context.uc_mcontext.gregs[REG_ERR]; - #endif -#elif defined(__aarch64__) - caller_address = reinterpret_cast(context.uc_mcontext.pc); -#endif - - switch (sig) - { - case SIGSEGV: - { - /// Print info about address and reason. - if (nullptr == info.si_addr) - LOG_ERROR(log, "Address: NULL pointer."); - else - LOG_ERROR(log, "Address: " << info.si_addr); - -#if defined(__x86_64__) && !defined(__FreeBSD__) && !defined(__APPLE__) - if ((err_mask & 0x02)) - LOG_ERROR(log, "Access: write."); - else - LOG_ERROR(log, "Access: read."); -#endif - - switch (info.si_code) - { - case SEGV_ACCERR: - LOG_ERROR(log, "Attempted access has violated the permissions assigned to the memory area."); - break; - case SEGV_MAPERR: - LOG_ERROR(log, "Address not mapped to object."); - break; - default: - LOG_ERROR(log, "Unknown si_code."); - break; - } - break; - } - - case SIGBUS: - { - switch (info.si_code) - { - case BUS_ADRALN: - LOG_ERROR(log, "Invalid address alignment."); - break; - case BUS_ADRERR: - LOG_ERROR(log, "Non-existant physical address."); - break; - case BUS_OBJERR: - LOG_ERROR(log, "Object specific hardware error."); - break; - - // Linux specific -#if defined(BUS_MCEERR_AR) - case BUS_MCEERR_AR: - LOG_ERROR(log, "Hardware memory error: action required."); - break; -#endif -#if defined(BUS_MCEERR_AO) - case BUS_MCEERR_AO: - LOG_ERROR(log, "Hardware memory error: action optional."); - break; -#endif - - default: - LOG_ERROR(log, "Unknown si_code."); - break; - } - break; - } - - case SIGILL: - { - switch (info.si_code) - { - case ILL_ILLOPC: - LOG_ERROR(log, "Illegal opcode."); - break; - case ILL_ILLOPN: - LOG_ERROR(log, "Illegal operand."); - break; - case ILL_ILLADR: - LOG_ERROR(log, "Illegal addressing mode."); - break; - case ILL_ILLTRP: - LOG_ERROR(log, "Illegal trap."); - break; - case ILL_PRVOPC: - LOG_ERROR(log, "Privileged opcode."); - break; - case ILL_PRVREG: - LOG_ERROR(log, "Privileged register."); - break; - case ILL_COPROC: - LOG_ERROR(log, "Coprocessor error."); - break; - case ILL_BADSTK: - LOG_ERROR(log, "Internal stack error."); - break; - default: - LOG_ERROR(log, "Unknown si_code."); - break; - } - break; - } - - case SIGFPE: - { - switch (info.si_code) - { - case FPE_INTDIV: - LOG_ERROR(log, "Integer divide by zero."); - break; - case FPE_INTOVF: - LOG_ERROR(log, "Integer overflow."); - break; - case FPE_FLTDIV: - LOG_ERROR(log, "Floating point divide by zero."); - break; - case FPE_FLTOVF: - LOG_ERROR(log, "Floating point overflow."); - break; - case FPE_FLTUND: - LOG_ERROR(log, "Floating point underflow."); - break; - case FPE_FLTRES: - LOG_ERROR(log, "Floating point inexact result."); - break; - case FPE_FLTINV: - LOG_ERROR(log, "Floating point invalid operation."); - break; - case FPE_FLTSUB: - LOG_ERROR(log, "Subscript out of range."); - break; - default: - LOG_ERROR(log, "Unknown si_code."); - break; - } - break; - } - } - - static const int max_frames = 50; - void * frames[max_frames]; - -#if USE_UNWIND - int frames_size = backtraceLibUnwind(frames, max_frames, context); - - if (frames_size) - { -#else - /// No libunwind means no backtrace, because we are in a different thread from the one where the signal happened. - /// So at least print the function where the signal happened. - if (caller_address) - { - frames[0] = caller_address; - int frames_size = 1; -#endif - - char ** symbols = backtrace_symbols(frames, frames_size); - - if (!symbols) - { - if (caller_address) - LOG_ERROR(log, "Caller address: " << caller_address); - } - else - { - for (int i = 0; i < frames_size; ++i) - { - /// Perform demangling of names. Name is in parentheses, before '+' character. - - char * name_start = nullptr; - char * name_end = nullptr; - char * demangled_name = nullptr; - int status = 0; - - if (nullptr != (name_start = strchr(symbols[i], '(')) - && nullptr != (name_end = strchr(name_start, '+'))) - { - ++name_start; - *name_end = '\0'; - demangled_name = abi::__cxa_demangle(name_start, 0, 0, &status); - *name_end = '+'; - } - - std::stringstream res; - - res << i << ". "; - - if (nullptr != demangled_name && 0 == status) - { - res.write(symbols[i], name_start - symbols[i]); - res << demangled_name << name_end; - } - else - res << symbols[i]; - - LOG_ERROR(log, res.rdbuf()); - } - } - } + LOG_ERROR(log, signalToErrorMessage(sig, info, context)); + LOG_ERROR(log, stack_trace.toString()); } }; diff --git a/libs/libloggers/loggers/ExtendedLogChannel.cpp b/libs/libloggers/loggers/ExtendedLogChannel.cpp index 857765a94de..8040a094a15 100644 --- a/libs/libloggers/loggers/ExtendedLogChannel.cpp +++ b/libs/libloggers/loggers/ExtendedLogChannel.cpp @@ -25,7 +25,11 @@ ExtendedLogMessage ExtendedLogMessage::getFrom(const Poco::Message & base) msg_ext.time_microseconds = static_cast(tv.tv_usec); if (current_thread) - msg_ext.query_id = CurrentThread::getQueryId(); + { + auto query_id_ref = CurrentThread::getQueryId(); + if (query_id_ref.size) + msg_ext.query_id.assign(query_id_ref.data, query_id_ref.size); + } msg_ext.thread_number = getThreadNumber(); diff --git a/libs/libmysqlxx/CMakeLists.txt b/libs/libmysqlxx/CMakeLists.txt index 166c10e69f7..263a031d7b0 100644 --- a/libs/libmysqlxx/CMakeLists.txt +++ b/libs/libmysqlxx/CMakeLists.txt @@ -12,7 +12,6 @@ add_library (mysqlxx include/mysqlxx/Connection.h include/mysqlxx/Exception.h - include/mysqlxx/Manip.h include/mysqlxx/mysqlxx.h include/mysqlxx/Null.h include/mysqlxx/Pool.h diff --git a/libs/libmysqlxx/include/mysqlxx/Manip.h b/libs/libmysqlxx/include/mysqlxx/Manip.h deleted file mode 100644 index 4b777b68f21..00000000000 --- a/libs/libmysqlxx/include/mysqlxx/Manip.h +++ /dev/null @@ -1,483 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include -#include -#include - - -namespace mysqlxx -{ - -/** @brief Манипулятор ostream, который escape-ит строки для записи в tab delimited файл. - * Использование: tab_separated_ostr << mysqlxx::escape << x; - */ -enum escape_enum -{ - escape -}; - - -/** @brief Манипулятор ostream, который quote-ит строки для записи в MySQL запрос. - * Внимание! Не использует функции MySQL API, а использует свой метод quote-инга, - * который может быть некорректным при использовании некоторых кодировок - * (multi-byte attack), а также может оказаться некорректным при изменении libmysqlclient. - * Это сделано для увеличения производительности и это имеет значение. - * - * Использование: query << mysqlxx::quote << x; - */ -enum quote_enum -{ - quote -}; - - -struct EscapeManipResult -{ - std::ostream & ostr; - - EscapeManipResult(std::ostream & ostr_) : ostr(ostr_) {} - - std::ostream & operator<< (bool value) { return ostr << static_cast(value); } - std::ostream & operator<< (char value) { return ostr << static_cast(value); } - std::ostream & operator<< (unsigned char value) { return ostr << static_cast(value); } - std::ostream & operator<< (signed char value) { return ostr << static_cast(value); } - - template - typename std::enable_if::value, std::ostream &>::type - operator<< (T value) { return ostr << value; } - - std::ostream & operator<< (const LocalDate & value) { return ostr << value; } - std::ostream & operator<< (const LocalDateTime & value) { return ostr << value; } - - std::ostream & operator<< (const std::string & value) - { - writeEscapedData(value.data(), value.length()); - return ostr; - } - - - std::ostream & operator<< (const char * value) - { - while (const char * it = std::strpbrk(value, "\t\n\\")) - { - ostr.write(value, it - value); - switch (*it) - { - case '\t': - ostr.write("\\t", 2); - break; - case '\n': - ostr.write("\\n", 2); - break; - case '\\': - ostr.write("\\\\", 2); - break; - default: - ; - } - value = it + 1; - } - return ostr << value; - } - - - std::ostream & operator<< (const Value & string) - { - writeEscapedData(string.data(), string.size()); - return ostr; - } - - - std::ostream & operator<< (const Row & row) - { - for (size_t i = 0; i < row.size(); ++i) - { - if (i != 0) - ostr << '\t'; - - if (row[i].isNull()) - { - ostr << "\\N"; - continue; - } - - (*this) << row[i]; - } - - return ostr; - } - - - template - std::ostream & operator<< (const Null & value) - { - if(value.is_null) - ostr << "\\N"; - else - *this << value.data; - - return ostr ; - } - - - template - std::ostream & operator<< (const std::vector & value) - { - throw Poco::Exception(std::string(__PRETTY_FUNCTION__) + " is not implemented"); - } - -private: - - void writeEscapedData(const char * data, size_t length) - { - size_t i = 0; - - while (true) - { - size_t remaining_length = std::strlen(data); - (*this) << data; - if (i + remaining_length == length) - break; - - ostr.write("\\0", 2); - i += remaining_length + 1; - data += remaining_length + 1; - } - } -}; - -inline EscapeManipResult operator<< (std::ostream & ostr, escape_enum manip) -{ - return EscapeManipResult(ostr); -} - - -struct QuoteManipResult -{ -public: - std::ostream & ostr; - - QuoteManipResult(std::ostream & ostr_) : ostr(ostr_) {} - - std::ostream & operator<< (bool value) { return ostr << static_cast(value); } - std::ostream & operator<< (char value) { return ostr << static_cast(value); } - std::ostream & operator<< (unsigned char value) { return ostr << static_cast(value); } - std::ostream & operator<< (signed char value) { return ostr << static_cast(value); } - - template - typename std::enable_if::value, std::ostream &>::type - operator<< (T value) { return ostr << value; } - - std::ostream & operator<< (const LocalDate & value) { return ostr << '\'' << value << '\''; } - std::ostream & operator<< (const LocalDateTime & value) { return ostr << '\'' << value << '\''; } - - std::ostream & operator<< (const std::string & value) - { - ostr.put('\''); - writeEscapedData(value.data(), value.length()); - ostr.put('\''); - - return ostr; - } - - - std::ostream & operator<< (const char * value) - { - ostr.put('\''); - writeEscapedCString(value); - ostr.put('\''); - return ostr; - } - - template - std::ostream & operator<< (const Null & value) - { - if(value.is_null) - { - ostr << "\\N"; - } - else - { - *this << value.data; - } - return ostr ; - } - - template - std::ostream & operator<< (const std::vector & value) - { - throw Poco::Exception(std::string(__PRETTY_FUNCTION__) + " is not implemented"); - } - -private: - - void writeEscapedCString(const char * value) - { - while (const char * it = std::strpbrk(value, "'\\\"")) - { - ostr.write(value, it - value); - switch (*it) - { - case '"': - ostr.write("\\\"", 2); - break; - case '\'': - ostr.write("\\'", 2); - break; - case '\\': - ostr.write("\\\\", 2); - break; - default: - ; - } - value = it + 1; - } - ostr << value; - } - - - void writeEscapedData(const char * data, size_t length) - { - size_t i = 0; - - while (true) - { - size_t remaining_length = std::strlen(data); - writeEscapedCString(data); - if (i + remaining_length == length) - break; - - ostr.write("\\0", 2); - i += remaining_length + 1; - data += remaining_length + 1; - } - } -}; - -inline QuoteManipResult operator<< (std::ostream & ostr, quote_enum manip) -{ - return QuoteManipResult(ostr); -} - - -/** Манипулятор istream, позволяет считывать значения из tab delimited файла. - */ -enum unescape_enum -{ - unescape -}; - - -/** Манипулятор istream, который позволяет читать значения в кавычках или без. - */ -enum unquote_enum -{ - unquote -}; - - -inline void parseEscapeSequence(std::istream & istr, std::string & value) -{ - char c = istr.get(); - if (!istr.good()) - throw Poco::Exception("Cannot parse string: unexpected end of input."); - - switch(c) - { - case 'b': - value.push_back('\b'); - break; - case 'f': - value.push_back('\f'); - break; - case 'n': - value.push_back('\n'); - break; - case 'r': - value.push_back('\r'); - break; - case 't': - value.push_back('\t'); - break; - default: - value.push_back(c); - break; - } -} - - -struct UnEscapeManipResult -{ - std::istream & istr; - - UnEscapeManipResult(std::istream & istr_) : istr(istr_) {} - - std::istream & operator>> (bool & value) { int tmp = 0; istr >> tmp; value = tmp; return istr; } - std::istream & operator>> (char & value) { int tmp = 0; istr >> tmp; value = tmp; return istr; } - std::istream & operator>> (unsigned char & value) { int tmp = 0; istr >> tmp; value = tmp; return istr; } - std::istream & operator>> (signed char & value) { int tmp = 0; istr >> tmp; value = tmp; return istr; } - - template - typename std::enable_if::value, std::istream &>::type - operator>> (T & value) { return istr >> value; } - - std::istream & operator>> (std::string & value) - { - value.clear(); - - char c; - while (1) - { - istr.get(c); - if (!istr.good()) - break; - - switch (c) - { - case '\\': - parseEscapeSequence(istr, value); - break; - - case '\t': - istr.unget(); - return istr; - break; - - case '\n': - istr.unget(); - return istr; - break; - - default: - value.push_back(c); - break; - } - } - return istr; - } - - /// Чтение NULL-able типа. - template - std::istream & operator>> (Null & value) - { - char c; - istr.get(c); - if (c == '\\' && istr.peek() == 'N') - { - value.is_null = true; - istr.ignore(); - } - else - { - istr.unget(); - value.is_null = false; - *this >> value.data; - } - return istr; - } - - std::istream & operator>> (LocalDate & value) - { - std::string s; - (*this) >> s; - value = LocalDate(s); - return istr; - } - - std::istream & operator>> (LocalDateTime & value) - { - std::string s; - (*this) >> s; - value = LocalDateTime(s); - return istr; - } - - template - std::istream & operator>> (std::vector & value) - { - throw Poco::Exception(std::string(__PRETTY_FUNCTION__) + " is not implemented"); - } -}; - -inline UnEscapeManipResult operator>> (std::istream & istr, unescape_enum manip) -{ - return UnEscapeManipResult(istr); -} - - -struct UnQuoteManipResult -{ -public: - std::istream & istr; - - UnQuoteManipResult(std::istream & istr_) : istr(istr_) {} - - std::istream & operator>> (bool & value) { int tmp = 0; istr >> tmp; value = tmp; return istr; } - std::istream & operator>> (char & value) { int tmp = 0; istr >> tmp; value = tmp; return istr; } - std::istream & operator>> (unsigned char & value) { int tmp = 0; istr >> tmp; value = tmp; return istr; } - std::istream & operator>> (signed char & value) { int tmp = 0; istr >> tmp; value = tmp; return istr; } - - template - typename std::enable_if::value, std::istream &>::type - operator>> (T & value) { return istr >> value; } - - std::istream & operator>> (std::string & value) - { - value.clear(); - readQuote(); - - char c; - while (1) - { - istr.get(c); - if (!istr.good()) - break; - - switch (c) - { - case '\\': - parseEscapeSequence(istr, value); - break; - - case '\'': - return istr; - break; - - default: - value.push_back(c); - break; - } - } - throw Poco::Exception("Cannot parse string: unexpected end of input."); - } - - template - std::istream & operator>> (std::vector & value) - { - throw Poco::Exception(std::string(__PRETTY_FUNCTION__) + " is not implemented"); - } - -private: - - void readQuote() - { - char c = istr.get(); - if (!istr.good()) - throw Poco::Exception("Cannot parse string: unexpected end of input."); - if (c != '\'') - throw Poco::Exception("Cannot parse string: missing opening single quote."); - } -}; - -inline UnQuoteManipResult operator>> (std::istream & istr, unquote_enum manip) -{ - return UnQuoteManipResult(istr); -} - - -} diff --git a/libs/libmysqlxx/include/mysqlxx/mysqlxx.h b/libs/libmysqlxx/include/mysqlxx/mysqlxx.h index f9da8ec5c04..179d550519e 100644 --- a/libs/libmysqlxx/include/mysqlxx/mysqlxx.h +++ b/libs/libmysqlxx/include/mysqlxx/mysqlxx.h @@ -2,7 +2,6 @@ #include #include -#include #include #include #include diff --git a/libs/libmysqlxx/src/tests/mysqlxx_test.cpp b/libs/libmysqlxx/src/tests/mysqlxx_test.cpp index d8c15eecaba..d99900b1a39 100644 --- a/libs/libmysqlxx/src/tests/mysqlxx_test.cpp +++ b/libs/libmysqlxx/src/tests/mysqlxx_test.cpp @@ -2,7 +2,7 @@ #include -int main(int argc, char ** argv) +int main(int, char **) { try { @@ -25,10 +25,10 @@ int main(int argc, char ** argv) << ", " << row[1].getDate() << ", " << row[1].getDateTime() << std::endl - << mysqlxx::escape << row[1].getDate() << ", " << mysqlxx::escape << row[1].getDateTime() << std::endl - << mysqlxx::quote << row[1].getDate() << ", " << mysqlxx::quote << row[1].getDateTime() << std::endl - << mysqlxx::escape << row[1].getDate() << ", " << mysqlxx::escape << row[1].getDateTime() << std::endl - << mysqlxx::quote << row[1].getDate() << ", " << mysqlxx::quote << row[1].getDateTime() << std::endl + << row[1].getDate() << ", " << row[1].getDateTime() << std::endl + << row[1].getDate() << ", " << row[1].getDateTime() << std::endl + << row[1].getDate() << ", " << row[1].getDateTime() << std::endl + << row[1].getDate() << ", " << row[1].getDateTime() << std::endl ; time_t t1 = row[0]; @@ -51,7 +51,7 @@ int main(int argc, char ** argv) mysqlxx::UseQueryResult result = connection.query("SELECT 'abc\\\\def' x").use(); mysqlxx::Row row = result.fetch(); std::cerr << row << std::endl; - std::cerr << mysqlxx::escape << row << std::endl; + std::cerr << row << std::endl; } { @@ -71,7 +71,7 @@ int main(int argc, char ** argv) for (Queries::iterator it = queries.begin(); it != queries.end(); ++it) { std::cerr << it->str() << std::endl; - std::cerr << mysqlxx::escape << it->store().at(0) << std::endl; + std::cerr << it->store().at(0) << std::endl; } } @@ -95,7 +95,7 @@ int main(int argc, char ** argv) for (Queries::iterator it = queries.begin(); it != queries.end(); ++it) { std::cerr << it->str() << std::endl; - std::cerr << mysqlxx::escape << it->store().at(0) << std::endl; + std::cerr << it->store().at(0) << std::endl; } } diff --git a/utils/check-marks/CMakeLists.txt b/utils/check-marks/CMakeLists.txt index 86cff8fb233..bfb200b8d28 100644 --- a/utils/check-marks/CMakeLists.txt +++ b/utils/check-marks/CMakeLists.txt @@ -1,2 +1,2 @@ add_executable (check-marks main.cpp) -target_link_libraries(check-marks PRIVATE clickhouse_compression clickhouse_common_io ${Boost_PROGRAM_OPTIONS_LIBRARY}) +target_link_libraries(check-marks PRIVATE dbms ${Boost_PROGRAM_OPTIONS_LIBRARY}) diff --git a/utils/compressor/CMakeLists.txt b/utils/compressor/CMakeLists.txt index e4f99c4b73a..3fdf8aa5eaf 100644 --- a/utils/compressor/CMakeLists.txt +++ b/utils/compressor/CMakeLists.txt @@ -10,7 +10,7 @@ add_executable (mutator mutator.cpp) target_link_libraries(mutator PRIVATE clickhouse_common_io) add_executable (decompress_perf decompress_perf.cpp) -target_link_libraries(decompress_perf PRIVATE clickhouse_common_io clickhouse_compression ${LZ4_LIBRARY}) +target_link_libraries(decompress_perf PRIVATE dbms ${LZ4_LIBRARY}) if (NOT USE_INTERNAL_ZSTD_LIBRARY AND ZSTD_INCLUDE_DIR) target_include_directories (zstd_test BEFORE PRIVATE ${ZSTD_INCLUDE_DIR}) diff --git a/utils/release/push_packages b/utils/release/push_packages index a32ceb0777f..d432136a5bd 100755 --- a/utils/release/push_packages +++ b/utils/release/push_packages @@ -6,6 +6,7 @@ import os import logging import shutil import base64 +import pexpect # Do nothing if keys are not provided @@ -116,6 +117,20 @@ def debsign(path, gpg_passphrase, gpg_sec_key_path, gpg_pub_key_path, gpg_user): logging.error("Cannot debsign packages on path %s, with user key", path) raise ex +def rpmsign(path, gpg_passphrase, gpg_sec_key_path, gpg_pub_key_path, gpg_user): + try: + with GpgKey(gpg_sec_key_path, gpg_pub_key_path): + for package in os.listdir(path): + package_path = os.path.join(path, package) + logging.info("Signing %s", package_path) + proc = pexpect.spawn('rpm --resign -D "_signature gpg" -D "_gpg_name {username}" {package}'.format(username=gpg_user, package=package_path)) + proc.expect_exact("Enter pass phrase: ") + proc.sendline(gpg_passphrase) + proc.expect(pexpect.EOF) + logging.info("Signed successfully") + except Exception as ex: + logging.error("Cannot rpmsign packages on path %s, with user key", path) + raise ex def transfer_packages_scp(ssh_key, path, repo_user, repo_url, incoming_directory): logging.info("Transferring packages via scp to %s", repo_url) @@ -212,6 +227,7 @@ if __name__ == "__main__": if args.rpm_directory: if not is_open_source: raise Exception("Cannot upload .rpm package to {}".format(args.repo_url)) + rpmsign(args.rpm_directory, args.gpg_passphrase, args.gpg_sec_key_path, args.gpg_pub_key_path, args.gpg_key_user) packages.append((args.rpm_directory, 'rpm')) if args.tgz_directory: diff --git a/website/deprecated/reference_en.html b/website/deprecated/reference_en.html index a789aeb238d..2e6fe0ac30b 100644 --- a/website/deprecated/reference_en.html +++ b/website/deprecated/reference_en.html @@ -7014,7 +7014,7 @@ Maximum nesting depth of a query syntactic tree. If exceeded, an exception is th ===max_ast_elements=== Maximum number of elements in a query syntactic tree. If exceeded, an exception is thrown. -In the same way as the previous setting, it is checked only after parsing the query. By default, 10,000. +In the same way as the previous setting, it is checked only after parsing the query. By default, 50,000. ===max_rows_in_set=== diff --git a/website/deprecated/reference_ru.html b/website/deprecated/reference_ru.html index e18966ae322..89c91d7d1c1 100644 --- a/website/deprecated/reference_ru.html +++ b/website/deprecated/reference_ru.html @@ -7260,7 +7260,7 @@ any (только для group_by_overflow_mode) - продолжить агре ===max_ast_elements=== Максимальное количество элементов синтаксического дерева запроса. Если превышено - кидается исключение. -Аналогично, проверяется уже после парсинга запроса. По умолчанию: 10 000. +Аналогично, проверяется уже после парсинга запроса. По умолчанию: 50 000. ===max_rows_in_set=== diff --git a/website/index.html b/website/index.html index 54e2958498c..e87223555fd 100644 --- a/website/index.html +++ b/website/index.html @@ -444,6 +444,8 @@ clickhouse-client rel="external nofollow" target="_blank">English or in Russian. +
  • Watch video content on YouTube channel.
  • Follow official Twitter account.