Pull to refresh

О том, как мелкие баги в линкере Microsoft аукаются в Linux, на примере Firefox

Reading time2 min
Views1.4K
image
Как известно, некоторое время назад команда Mozilla наступила на баг в линкере микрософт — xul.dll получалась такая богатая, что линкер на ней падал. И собрать версию под платформу номер один (windows 32bit) не удавалось.

Временно, до выяснения, из Firefox были выкинуты «малоиспользуемые» API. Произошло это между 5 и 7й версиями.

Не будет сюрпризом тот факт, что борьба за линкер была продолжена, о чем у нас и пойдет речь.


— Что это, Бэрримор?


Для начала, обрезания удостоился самый «вкусный» для меня раздел — embedding. Мозилловцы мощно прошлись электрокосой, оставив лишь охвостья для андроидов. Печально, но факт. А инкубаторовское «новое» апи — так в инкубаторе и застряло.

Но затем удостоился чести пропасть JavaXPCOM, а вот это уже был мощный удар по моим экспериментам.

Так что внедрениям огнелиса под Linux (и где тот линкер микрософт?) настал алес капут пришлось потесниться и что-то делать в консерватории.

— Овсянка, сэр!


В качестве ответного хода, был выбран «устаревший» gtkmozembed (как более компактный для поддержки) и я его с 7й по 14ю версию тяну в виде патча. А огнелис теперь собираю из сырцов, спасибо микрософт кривым рукам мозилловцев «временному» решению, которое как всегда стало постоянным.

В виде бесплатного бонуса, я пережил бодрые смены API firefox, потом — новые интерфейсы для login (prompt service), затем странности с principal URL, потом было переименование PRBool в bool, и к 10й версии резерв пространства снова был исчерпан.

— Темза, сэр!


Далее начались танцы с бубном и камлание. Часть кода (причем весьма неожиданная) переехала из xul.dll в firefox.exe. Например, jemalloc.

Так что я был этому очень «рад», когда словил странные падения огнелиса в libsqlite3. Пересборка с отладкой выдала потрясающий дамп — падение произошло на вызове
size_t je_malloc_usable_size_in_advance(size_t size);

Недоумевая, как это так может быть, я написал строчкой выше
printf("strange crash below: je_malloc_usable_size_in_advance(%p) (%d)\n",
    je_malloc_usable_size_in_advance, size);

и полюбовался на длинный ряд нулей в качестве адреса функции.

— Ровно выпирать насяльника, вааай!


Изучение сырцов огнелиса 10й версии сообщило о хаке, используемом самими мозилловцами:
LIBS+=-Wl,--whole-archive libmozglue.a -Wl,--no-whole-archive -rdynamic

И разумеется, эта самая libmozglue.a не попала в пакет firefox_dev — это было на сладкое.

В 11 версии firefox секретная libmozglue.a самопереименовалась в libmozutil.a, а в 13й версии вернула свое посконное название.

В этой же 13й версии в libmozglue переехал маленький и незаметный каталог mbft. В котором то и было тьфу и ничего — HashBytes. Без которой можно долго недоумевать — а чего это оно в libc падает? Вот поэтому падает, что HashKey(nsCID&) зовет HashBytes. А HashBytes в отличие от HashString — в .cpp. И мы имеем null pointer на plain C table->op->hash(key) — HashBytes осталась стабом.

В 14й версии сменился апи для Javascript и даже банальщина JS_GC(context) превратилась в JS_GC(JS_GetRuntime(context)). Как хорошо, что мне от javascript всего-то и надо как полторы функции!

Теперь я патчу Firefox 14.0.1, и слежу за развитием событий. Продолжение следует?
Tags:
Hubs:
Total votes 110: ↑95 and ↓15+80
Comments50

Articles