1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.

Отладка ядра и расширений ядра

Тема в разделе 'Хакинтош', создана пользователем vit9696, 2 дек 2016.

  1. vit9696

    vit9696 Apple Life Dev Разработчик

    Симпатии:
    1`436
    Существуют условно три вида отладки ПО по назначению:
    • прикладной (userspace): запускаемые исполняемые файлы, библиотеки, фреймворки;
    • системы или ядра (kernelspace): ядро, расширения ядра;
    • прошивки (bios/uefi): модули прошивки, протоколы.
    Первое нас в целом не интересует, материала в сети много. Третье в принципе тоже, отладка обычно осуществляется либо через COM, либо через USB, по edk2 есть информация тут.

    В macOS отладка ядра (xnu) и загружаемых модулей (kext) в отличие от Windows, где был SoftICE, происходит с помощью двух машин*:
    1. хост — машина с запущенным отладчиком, в котором мы работаем;
    2. таргет — машина, которую мы отлаживаем.
    На каждой машине желательно иметь macOS, в идеале одинаковых версий, но не обязательно. Стоит отметить, что во время паузы отладки на таргете будет 100% использование CPU, так как отладчик уходит в busy loop, в случае с ноутбуками это довольно критично. Отладка возможна на данный момент как минимум с помощью трёх отладчиков:
    1. gdb — классический способ, описан на сайте Apple;
    2. lldb — пришёл на замену gdb, описан в инструкции к kdk;
    3. ddb — отладка с помощью локального сервера через COM-порт, также называется kdb.
    Физически возможны несколько вариантов отладки, примеры с железом и виртуалками, у кого как получилось, можно обсудить ниже. Условно варианты:
    • Ethernet LAN (built-in, Thunderbolt, PCI/PCIe) — lldb/gdb;
    • Firewire (built-in, Thunderbolt, PCI/PCIe) — lldb/gdb;
    • Serial (built-in, PCI/PCIe) — ddb;
    Отладка во всех случаях осуществляется с помощью следующего алгоритма:
    1. Отключаем System Integrity Protection (если он есть), а именно флаг kernel debugger;
    2. Производим физические манипуляции для последующей стыковки машин;
    3. Выставляем аргументы загрузки (boot-args):
      • debug=МАСКА;
      • [опционально] kcsuffix=суффикс_ядра (debug, development, начиная с 10.10);
      • [опционально] cpus=1 (один процессор для облегчения трейсинга);
      • [опционально] slide=0 (отключение KASLR);
      • [опционально] pmuflags=1 (отключение watchdog при наличии серверных компонентов);
      • Существует множество других, как специфичных для способа отладки, так и специфичных для самой отладки (их легко найти по PE_parse_boot_argn в коде ядра).
      Биты аргумента debug (как видно, можно остановить машину сразу в процессе загрузки, так и подождать паники, например):
      Код:
      #define DB_HALT             0x1 // halt cpu at boot
      #define DB_PRT              0x2 // debug output to console
      #define DB_NMI              0x4 // break by non maskable interrupts (CMD+Power, CMD+OPT+CTRL+Shift+Esc, Interrupt switch)
      #define DB_KPRT             0x8 // debug output to serial
      #define DB_KDB             0x10 // make kdb/ddb the default debugger
      #define DB_SLOG            0x20 // various messages to system log
      #define DB_ARP             0x40 // ARP responses
      #define DB_KDP_BP_DIS      0x80 // local breakpoint support (KDP_FEATURE_BP, for old gdb)
      #define DB_LOG_PI_SCRN    0x100 // print panic on screen
      #define DB_KDP_GETC_ENA   0x200 // enable keyboard c (continue), r (reboot) on debug wait
      #define DB_KERN_DUMP_ON_PANIC     0x400 /* Trigger core dump on panic*/
      #define DB_KERN_DUMP_ON_NMI       0x800 /* Trigger core dump on NMI */
      #define DB_DBG_POST_CORE         0x1000 /* Wait in debugger after NMI core */
      #define DB_PANICLOG_DUMP         0x2000 /* Send paniclog on panic,not core*/
      #define DB_REBOOT_POST_CORE      0x4000 /* Attempt to reboot after post-panic crashdump/paniclog dump. */
      #define DB_NMI_BTN_ENA           0x8000 /* Enable button to directly trigger NMI */
      #define DB_PRT_KDEBUG           0x10000 /* kprintf KDEBUG traces */
      #define DB_DISABLE_LOCAL_CORE   0x20000 /* ignore local kernel core dump support */
      #define DB_DISABLE_GZIP_CORE    0x40000 /* don't gzip kernel core dumps */
    4. Запускаем хост и таргет;
    5. Цепляемся отладчиком на хосте к таргету на каком-то этапе;
    6. Работаем.
    Ethernet
    Здесь всё просто, отладка происходит через кекст сетевой карты, который реализует протокол IOKernelDebugger. Компьютеры находятся в локальной сети и видят друг друга по IP-адресу. Посмотреть пример реализации протокола можно в исходном коде AppleIntel8255x. В числе родных кекстов macOS не все поддерживают этот протокол:
    • AppleBCM5701Ethernet.kext (используется в Thunderbolt переходнике и новых маках)
    • AppleIntel8254XEthernet.kext (работает правильно в VMware, в Parallels, на реальном железе)
    • AppleIntelI210Ethernet.kext — не поддерживает
    • AppleVmxnet3Ethernet.kext — не поддерживает
    • AppleYukon2.kext
    • Intel82574L.kext (работает криво как минимум на VMware, есть PCIe карты)
    • nvenet.kext (встроенные сетевые на MCP79-1, MCP79-2, MCP89)
    Драйвера хаков написаны весьма странным образом, и как следствие, пока ни один из встреченных мной этот протокол не поддерживает. Добавить достаточно просто, в качестве примера неполный дифф для E1000e (требуется реализация sendPacket/receivePacket — непосредственно протокола сообщения):
    Show Spoiler
    Код:
    $ svn diff
    Index: AppleIntelE1000e.cpp
    ===================================================================
    --- AppleIntelE1000e.cpp    (revision 127)
    +++ AppleIntelE1000e.cpp    (working copy)
    @@ -1980,6 +1980,7 @@
    {
         e_dbg("void AppleIntelE1000e::free()\n");
    
    +    RELEASE(debugger);
         RELEASE(netif);
    
         RELEASE(pciDevice);
    @@ -2423,6 +2424,11 @@
                 break;
             }
    
    +        // Attach a kernel debugger client. This is not an essential service,
    +        // and the return is not checked.
    +
    +        attachDebuggerClient(&debugger);
    +
             e_dbg("start success.\n");
             success = true;
         } while(false);
    @@ -2507,7 +2513,7 @@
    }
    
    //---------------------------------------------------------------------------
    -IOReturn AppleIntelE1000e::enable(IONetworkInterface * netif)
    +IOReturn AppleIntelE1000e::enable(IONetworkInterface * /*netif*/)
    {
         e_dbg("AppleIntelE1000e::enable().\n");
    
    @@ -2569,7 +2575,7 @@
         return kIOReturnIOError;
    }
    
    -IOReturn AppleIntelE1000e::disable(IONetworkInterface * netif)
    +IOReturn AppleIntelE1000e::disable(IONetworkInterface * /*netif*/)
    {
         e_dbg("AppleIntelE1000e::disable().\n");
    
    @@ -2621,6 +2627,27 @@
         return kIOReturnSuccess;
    }
    
    +IOReturn AppleIntelE1000e::enable(IOKernelDebugger * /*debugger*/)
    +{
    +    if (enabledForDebugger || enabledForNetif) {
    +        enabledForDebugger = true;
    +        return kIOReturnSuccess;
    +    }
    +
    +    // Enable interface completely for now
    +    //TODO: implement activation levels like in Intel82557 (debugging -> full)
    +    enabledForDebugger = AppleIntelE1000e::enable(static_cast<IONetworkInterface *>(NULL)) == kIOReturnSuccess;
    +
    +    return ( enabledForDebugger ? kIOReturnSuccess : kIOReturnIOError );
    +}
    +
    +IOReturn AppleIntelE1000e::disable(IOKernelDebugger * /*debugger*/)
    +{
    +    enabledForDebugger = false;
    +
    +    return kIOReturnSuccess;
    +}
    +
    void AppleIntelE1000e::e1000e_up()
    {
         struct e1000_adapter *adapter = &priv_adapter;
    @@ -5608,8 +5635,28 @@
    #endif
    }
    
    +//---------------------------------------------------------------------------
    +// Kernel debugger entry points.
    +//
    +// KDP driven polling routines to send and transmit a frame.
    +// Remember, no memory allocation! Not even mbufs are safe.
    
    +void AppleIntelE1000e::sendPacket(void * pkt, UInt32 pkt_len)
    +{
    +    //txWatchdogArmed = false;
    +    //_sendPacket(pkt, pkt_len);
    +
    +    //TODO: implement
    +}
    
    +void AppleIntelE1000e::receivePacket(void * pkt, UInt32 * pkt_len, UInt32 timeout)
    +{
    +    //txWatchdogArmed = false;
    +    //_receivePacket(pkt, (UInt *) pkt_len, timeout);
    +
    +    //TODO: implement
    +}
    +
    UInt32 AppleIntelE1000e::getFeatures() const {
         UInt32 f = kIONetworkFeatureMultiPages | kIONetworkFeatureHardwareVlan;
         if(useTSO)
    Index: AppleIntelE1000e.h
    ===================================================================
    --- AppleIntelE1000e.h    (revision 127)
    +++ AppleIntelE1000e.h    (working copy)
    @@ -71,6 +71,12 @@
         virtual IOReturn enable(IONetworkInterface * netif);
         virtual IOReturn disable(IONetworkInterface * netif);
    
    +    virtual IOReturn enable(IOKernelDebugger * debugger);
    +    virtual IOReturn disable(IOKernelDebugger * debugger);
    +
    +    virtual void sendPacket(void * pkt, UInt32 pkt_len);
    +    virtual void receivePacket(void * pkt, UInt32 * pkt_len, UInt32 timeout);
    +
         virtual UInt32 outputPacket(mbuf_t m, void * param);
    
         virtual void getPacketBufferConstraints(IOPacketBufferConstraints * constraints) const;
    @@ -115,6 +121,7 @@
         IOTimerEventSource * resetSource;
    
         IOEthernetInterface * netif;
    +    IOKernelDebugger * debugger;
         IONetworkStats * netStats;
         IOEthernetStats * etherStats;
    
    @@ -125,6 +132,7 @@
         IOMbufNaturalMemoryCursor * txMbufCursor;
    
         bool enabledForNetif;
    +    bool enabledForDebugger;
         bool promiscusMode;
         bool multicastMode;
         bool stalled;

    По умолчанию ядро цепляется к адаптеру en0, однако это можно изменить, указав один из дополнительных аргументов загрузки:
    • kdp_match_mac=112233445566 — выбор сетевой по MAC-адресу;
    • kdp_match_name=en4 — выбор сетевой по BSD имени.
    Значения можно посмотреть из команды ifconfig:
    Код:
    $ ifconfig
    ….
    en4: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        options=b<RXCSUM,TXCSUM,VLAN_HWTAGGING>
        ether 11:22:33:44:55:66
        inet6 ...
        inet ...
        nd6 options=201<PERFORMNUD,DAD>
        media: autoselect
        status: active
    …
    Подключение из отладчика производится к IP-адресу, который сохранён для данной машины.

    FireWire
    В теории всё так же просто, но соединение девайсов происходит кабелем FireWire физически. На текущий момент нативные интерфейсы FireWire есть в MacPro6,1 и старых девайсах, так что для оригинального железа придётся покупать переходники.

    Для FireWire указывается аргумент загрузки kdp_match_name=firewire, при этом для невстроенных контроллеров будет ещё нужен fwkdp=0x8000.

    На хосте запускается процесс fwkdp, а подключение из отладчика производится к localhost.

    Serial
    Отладка через последовательный порт отличается от двух предыдущих тем, что она не зависит от кекстов сетевых карт и доступна практически сразу после запуска ядра. Сам отладчик встроен в ядро и подключение к нему производится с помощью любого COM терминала, например, команды screen или minicom. Скорость передачи 57600 бод, режим 8-N-1.

    Информации по этому режиму очень мало, и почти вся устаревшая. Тем не менее, стоит учитывать, что встроенный отладчик примитивен, не имеет скриптов и использовать его будет значительно менее удобно, чем любой другой. Также ddb в релизном ядре нужно либо включать в исходниках самому, с помощью дефайна CONFIG_SERIAL_KDP. Разумеется, можно и использовать ядра development/debug.

    Live Debugging *
    В старых системах (начиная с 10.5) была возможность ограниченной отладки в рамках одной машины с помощью gdb. Об использовании точек останова и прочего речи не идёт, но можно работать с памятью. Для этого в аргументы загрузки (кроме обычных) необходимо добавить kmem=1 (включает устройство /dev/kmem для работы с памятью ядра), а в gdb использовать target darwin-kernel.
    Подробности сохранились у Синга и в readme KDK 10.6.8:
    Show Spoiler
    Live (single-machine) kernel debugging was introduced in Leopard. This allows limited introspection of the kernel on a currently-running system.

    To use the live kernel debugger, first install the DEBUG kernel as shown above. Then do the following:

    $ sudo nvram boot-args="<your_current_boot-args> kmem=1"
    $ sudo shutdown -r now

    After rebooting, do:

    $ sudo gdb -a <arch> --quiet /mach_kernel
    (gdb) target darwin-kernel
    (gdb) source /Volumes/KernelDebugKit/kgmacros
    Loading Kernel GDB Macros package. Type "help kgm" for more info.
    (gdb) attach
    Connected.

    arch should reflect the currently booted kernel architecture, either i386 or x86_64.

    lldb
    Является основным средством отладки, начиная с 10.8. В принципе информации по нему пруд пруди, для тех, кто привык работать с gdb, вот соотношение команд gdb к lldb.

    lldb поддерживает отладку по исходному коду плюс в KDK есть множество макросов на питоне, упрощающих отладку (см.
    /Library/Developer/KDKs/KDK_<версия KDK>.kdk/System/Library/Kernels/kernel.<тип ядра>.dSYM/Contents/Resources/Python/lldbmacros). Их реально много и лучше просто прошерстить исходники поиском по @lldb_command.

    Пример сессии выглядит примерно так:
    Код:
    $ lldb /Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel.development
    settings set target.load-script-from-symbol-file true # подключить макросы на питоне
    kdp-remote <ip адрес или имя хоста>
    showlldbtypesummaries # позволяет облегчить вывод информации из различных структур
    # Исходники у Apple лежат по пути типа
    /Library/Caches/com.apple.xbs/Sources/xnu/xnu-3789.21.4/bsd/dev/dtrace/dtrace.c, соответственно нам их нужно мапить:
    settings set target.source-map /Library/Caches/com.apple.xbs/Sources/xnu /ваш/путь/к/папке/с/исходниками/xnu
    
    # Если планируется отлаживать расширения ядра...
    image add /Путь/к/расширению/ядра.kext # если планируется загружать кекст вручную
    b OSKextLoadedKextSummariesUpdated    # остановка сразу после загрузки любого кекста
    showallkmods # информация обо всех загруженных кекстах (читается из gLoadedKextSummaries)
    image lookup -a 0x1234566 --verbose # получение информации об адресе
    
    systemlog # лог системы
    
    # На совсем тяжёлый случай
    b <regex> # add breakpoint (address, symbol)
    s/si # step / step instruction (into)
    n/ni # next / next instruction (over)
    c   # continue
    register read
    p <regex> # print data (address, symbol)
    bt # stack trace
    Сторонние UI к lldb прилепить можно, и в принципе не так сложно:
    • Плагин для IDA от bootleg, допиленный для более адекватной работы с lldb: тут;
    • Простенький консольный интерфейс с автообновлением окон дизасма и регистров: тут;
    • Из коробки подключается к Hopper Disassembler (в окне отладчика есть Debugger Console, куда можно вбить команду kdp-remote… но пока не допилено, в какой-то из 4.x должно быть).
    TODO: gdb…
    P. S. Времени всё описывать нет, у кого есть желание — присылайте заготовки, поправлю, включу в FAQ.

    Ссылки на других языках:
    https://developer.apple.com/library...ncept/KEXTConceptDebugger/debug_tutorial.html
    https://developer.apple.com/library...Conceptual/KernelProgramming/build/build.html
    http://ddeville.me/2015/08/kernel-debugging-with-lldb-and-vmware-fusion
    https://reverse.put.as/2014/02/21/dont-die-gdb-we-love-you-kgmacros-ported-to-mavericks/
     
    Последнее редактирование: 29 янв 2017
    StarCom, eierfrucht, denskop и 11 другим нравится это.
     
  2. droplets

    droplets iГуру

    Симпатии:
    304
    Попробовал через Serial сделать вывод дебажной информации на другой компьютер. На десктопе один ком порт, на ноутбуке ком портов нет, но есть USB. Нужно будет подумать над форматированием вывода в файл (краозяблики).
    На десктопе 10.12.2 на ноутбуке 10.9.5 .Вывод информации с десктопа на ноутбук.
    Debug_Serial.
     
  3. vit9696

    vit9696 Apple Life Dev Разработчик

    Симпатии:
    1`436
    Честно говоря, на фото мне ничего не видно. Что за софтина, что не так с выводом, какой режим передачи и скорость…
     
  4. slice

    slice Apple Life Dev Разработчик

    Симпатии:
    8`029
    medik, ты где?
    Перенеси посты из "Черный экран радеона" сюда. Две или три последние страницы почти полностью.
     
  5. droplets

    droplets iГуру

    Симпатии:
    304
    Использую CoolTermV1.4.6.
    Конфигурация ком порта на десктопе
    Desktop.
    На ноутбуке конфигурация
    Notebook.
    Скорость портов выставлял разную. В hex вывод на втором скрине, в ASCII в аттаче.
    При выводе в аски не могу убрать служебные символы, хотя фильтры включаю.Может я что-то не догоняю. Соберу миником, может с ним что-то изменится
     

    Вложения:

    • new.asc.zip
      Размер файла:
      127.7 КБ
      Просмотров:
      0
  6. vit9696

    vit9696 Apple Life Dev Разработчик

    Симпатии:
    1`436
    На гистограмме присутствуют все значения, но довольно неравномерно. Я бы склонялся, что это не шум, а неверные параметры чтения.
    Тем не менее, в xnu изменилось столько всего, что я серьёзно сомневаюсь, что параметры из документации ещё подходят.
    @slice у тебя вроде получалось на современных осях работать с COM-портом, не поделишься опытом?

    Сейчас в ядре есть два бутарга по последовательному порту ещё:
    serial — маска, младший бит, равный единице, переводит данные в консоль;
    serialbaud — число, скорость передачи в бодах.
     
  7. tatur_sn

    tatur_sn iЮзер

    Симпатии:
    115
    Когда то давно пользовал такую хрень http://plugable.com/2011/07/12/installing-a-usb-serial-adapter-on-mac-os-x/
     
  8. nms42

    nms42 iЮзер

    Симпатии:
    109
    Нуль-модем нужен с RTS/CTS flow control.
     
  9. droplets

    droplets iГуру

    Симпатии:
    304
    Спасибо! Буду разбираться, но обычные текстовые файлы передаются нормально
    blog.
     
  10. droplets

    droplets iГуру

    Симпатии:
    304
    Кажется получилось.Скорость порта приемника имеет большое значение в данном случае.
    Show Spoiler


    LogOK.

     
    Последнее редактирование: 9 дек 2016
    chrome нравится это.
  11. nms42

    nms42 iЮзер

    Симпатии:
    109
    Я при получении отладочной выдачи в компорт держу окно принимающей программы (putty) в 2 строки.
     
  12. droplets

    droplets iГуру

    Симпатии:
    304
    Спасибо! Буду знать. На следующем этапе нужно разобраться как запускать приложения через ком порт (если это возможно). Давно это было,забыл напрочь все.
     
    Последнее редактирование: 9 дек 2016
  13. slice

    slice Apple Life Dev Разработчик

    Симпатии:
    8`029
    Да там нечем делиться, муль-модемный кабель, и настройки порта с обоих сторон. Желательна хорошая земля.
    А дальше как повезет. Последний опыт был в QEMU
    -serial stdio
     
    vit9696 и Moorre нравится это.
  14. droplets

    droplets iГуру

    Симпатии:
    304
    По поводу ком порта у меня возник небольшой вопрос. Почему если я указываю в бут-аргах ну например debug=0x108 или debug=0x08 , то ком порт удаляется из системы?
    Притворюсь, что я ничего не понимаю, но тогда .....?
    На скрине все видно
    DebugCom.
     
  15. nms42

    nms42 iЮзер

    Симпатии:
    109
    Так нормальной работы компорта не будет если еще и дебаг фигня по нему же ;-) Проще сделать несуществующим.
     
    droplets нравится это.
  16. droplets

    droplets iГуру

    Симпатии:
    304
    Прошусь в ликбез.. для особо одаренных. Если бут-аргах прописан флаг на отправку дебажной информации в ком порт, ком порт становится не существующим, но информация через него передается на приемник, что я наблюдал. Удаляем эти флаги , после перезагрузки ком порт активен, .... можно осуществлять пересылку файлов , а отладочную информацию через него могут передавать необходимым образом подготовленные приложния. Я правильно понял?
     
  17. vit9696

    vit9696 Apple Life Dev Разработчик

    Симпатии:
    1`436
    По-моему, сложилось какое-то нездоровое восприятие инфы из иорега.
    Если никакой кекст не вешается на устройство, то это значит только то, что никакой кекст на него не вешается. Никакой инфы по состоянию устройства это не даёт.
    При использовании флагов отладки COM-портом управляет XNU, никакие кексты для этого ему не нужны.
    Соответственно ни у пользователя, ни у прикладных программ доступа к COM-порту при таком раскладе не будет.

    Вы бы попробовали заюзать ddb, а не играться с логами, что вы в них собрались увидеть?
     
    Vandroiy, droplets и Moorre нравится это.
  18. RemB

    RemB iЮзер

    Симпатии:
    92
    Коротко для истории, как запустить отладку на хаке. Всё ниже описанное относиться к целевой (Target) машине. К ЭВМ с которой будет вестись отладка никаких особенных требований нет.

    1. Покупаем и устанавливаем сетевую карту EXPI9402PT (как пример, вот). Ставить лучше в первый слот - PCIe1, так он будет раньше детектить карту и загружать драйвера для неё. Возможно заработает и с другими сетевыми, например Intel 82574L, но не проверял.
    2. Пока едет карта разбираемся с клевером. В Кловер есть проблема при работе с kernel.debug и kernel.develop. Он не может определить ядро системы по имеющимся сигнатурам и как следствие не грузит внешние кексты, которые лежат в в Клевере. Самый важный из них, это FakeSMC.kext и если его не подгрузить система не поднимется. Тут два варианта:
    а) Просто скопировать перед инвалидацией кэша в /S/L/E FakeSMC.kext. Но при этом другие кексты из клевера грузится не будут (например AppleALC.kext), поэтому я пошел по второму пути.
    б) Пропатчить клевер, чтобы он начал понимать отладочные ядра. Патч у меня получился такой:
    Clover patch for debug kernel (open)
    Код:
    --- kext_inject.c    2016-12-05 09:21:00.000000000 +0700
    +++ /Users/roman/tmp/10.12.1/kext_inject.c    2017-01-21 20:12:36.000000000 +0700
    @@ -559,6 +559,17 @@
    UINT8   KBESieSearchSIP[]        = { 0xC3, 0x48, 0x85, 0xDB, 0x74, 0x71, 0x48, 0x8B, 0x03, 0x48, 0x89, 0xDF, 0xFF, 0x50, 0x28, 0x48 };
    UINT8   KBESieReplaceSIP[]       = { 0xC3, 0x48, 0x85, 0xDB, 0xEB, 0x12, 0x48, 0x8B, 0x03, 0x48, 0x89, 0xDF, 0xFF, 0x50, 0x28, 0x48 };
    
    +// Sierra [URL='https://applelife.ru/threads/otladka-jadra-i-rasshirenij-jadra.1768642/tags/debug/']debug[/URL] kernel
    +UINT8   KBESieDebugSearchEXT[]        = { 0xE8, 0x47, 0x00, 0x00, 0x00, 0xE9, 0x09, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x7D, 0xE8, 0xE8, 0xD9 };
    +UINT8   KBESieDebugReplaceEXT[]       = { 0xE8, 0x47, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0x8B, 0x7D, 0xE8, 0xE8, 0xD9 };
    +UINT8   KBESieDebugSearchSIP[]        = { 0x31, 0xC9, 0x39, 0xC1, 0x0F, 0x85, 0x3C, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x85, 0xF8, 0xFE, 0xFF };
    +UINT8   KBESieDebugReplaceSIP[]       = { 0x31, 0xC9, 0x39, 0xC1, 0xEB, 0x40, 0x90, 0x90, 0x90, 0x90, 0x48, 0x8B, 0x85, 0xF8, 0xFE, 0xFF };
    +
    +// Sierra develop kernel
    +UINT8   KBESieDevelSearchEXT[]        = { 0xE8, 0x25, 0x00, 0x00, 0x00, 0xEB, 0x05, 0xE8, 0xCE, 0x05, 0x00, 0x00, 0xE8, 0xC9, 0x08, 0x00 };
    +UINT8   KBESieDevelReplaceEXT[]       = { 0xE8, 0x25, 0x00, 0x00, 0x00, 0x90, 0x90, 0xE8, 0xCE, 0x05, 0x00, 0x00, 0xE8, 0xC9, 0x08, 0x00 };
    +UINT8   KBESieDevelSearchSIP[]        = { 0xC3, 0x48, 0x85, 0xDB, 0x74, 0x70, 0x48, 0x8B, 0x03, 0x48, 0x89, 0xDF, 0xFF, 0x50, 0x28, 0x48 };
    +UINT8   KBESieDevelReplaceSIP[]       = { 0xC3, 0x48, 0x85, 0xDB, 0xEB, 0x12, 0x48, 0x8B, 0x03, 0x48, 0x89, 0xDF, 0xFF, 0x50, 0x28, 0x48 };
    
    //
    // We can not rely on OSVersion global variable for OS version detection,
    @@ -580,6 +591,8 @@
       UINTN   NumYos = 0;
       UINTN   NumEC = 0;
       UINTN   NumSie = 0;
    +  UINTN   NumSieDebug = 0;
    +  UINTN   NumSieDevel = 0;
    
       DBG_RT(Entry, "\nPatching kernel for injected kexts...\n");
    
    @@ -590,6 +603,8 @@
         NumYos       = SearchAndCount(Kernel, KERNEL_MAX_SIZE, KBEYosSearchEXT, sizeof(KBEYosSearchEXT));
         NumEC        = SearchAndCount(Kernel, KERNEL_MAX_SIZE, KBEECSearchSIP, sizeof(KBEECSearchSIP));
         NumSie       = SearchAndCount(Kernel, KERNEL_MAX_SIZE, KBESieSearchSIP, sizeof(KBESieSearchSIP));
    +    NumSieDebug  = SearchAndCount(Kernel, KERNEL_MAX_SIZE, KBESieDebugSearchSIP, sizeof(KBESieDebugSearchSIP));
    +    NumSieDevel  = SearchAndCount(Kernel, KERNEL_MAX_SIZE, KBESieDevelSearchSIP, sizeof(KBESieDevelSearchSIP));
       } else {
         NumSnow_i386 = SearchAndCount(Kernel, KERNEL_MAX_SIZE, KBESnowSearchEXT_i386, sizeof(KBESnowSearchEXT_i386));
         NumLion_i386 = SearchAndCount(Kernel, KERNEL_MAX_SIZE, KBELionSearchEXT_i386, sizeof(KBELionSearchEXT_i386));
    @@ -637,7 +652,19 @@
                 SearchAndReplace(Kernel, KERNEL_MAX_SIZE, KBESieSearchSIP, sizeof(KBESieSearchSIP), KBESieReplaceSIP, 1);
           DBG_RT(Entry, "==> kernel Sierra: %d replaces done.\n", Num);
       }
    +  else if (NumSieDebug == 1) {
    +      Num = SearchAndReplace(Kernel, KERNEL_MAX_SIZE, KBESieDebugSearchEXT, sizeof(KBESieDebugSearchEXT), KBESieDebugReplaceEXT, 1) +
    +      SearchAndReplace(Kernel, KERNEL_MAX_SIZE, KBESieDebugSearchSIP, sizeof(KBESieDebugSearchSIP), KBESieDebugReplaceSIP, 1);
    +      DBG_RT(Entry, "==> kernel Sierra Debug: %d replaces done.\n", Num);
    +  }
    +  else if (NumSieDevel == 1) {
    +      Num = SearchAndReplace(Kernel, KERNEL_MAX_SIZE, KBESieDevelSearchEXT, sizeof(KBESieDevelSearchEXT), KBESieDevelReplaceEXT, 1) +
    +      SearchAndReplace(Kernel, KERNEL_MAX_SIZE, KBESieDevelSearchSIP, sizeof(KBESieDevelSearchSIP), KBESieDevelReplaceSIP, 1);
    +      DBG_RT(Entry, "==> kernel Sierra Development: %d replaces done.\n", Num);
    +  }
    +
    
    +
       // i386
       else if (NumSnow_i386 == 1) {
           Num = SearchAndReplace(Kernel, KERNEL_MAX_SIZE, KBESnowSearchEXT_i386, sizeof(KBESnowSearchEXT_i386), KBESnowReplaceEXT_i386, 1);

    Я собрал клевер ревизии 3977 с данным патчем, но так пока и не проверил. Приложил.
    3. Качаем KDK для установленной версии macOS и ставим. Копируем желаемое ядро (kernel.debug, kernel.develop) из /Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/ в /System/Library/Kernels/
    4. Делаем инвалидацию кэша: sudo kextcache -invalidate /
    5. Проверяем включена ли System Integrity Protection (SIP) командой «csrutil status». Кловер её выключает, но если включена, то выключаем через Кловер:
    Код:
         <key>RtVariables</key>
           <dict>
           <key>CsrActiveConfig</key>
           <string>0x67</string>
    6. Можно сразу добавить в nvram опции: sudo nvram boot-args="debug=0x141 kdp_match_name=en3 kcsuffix=debug» или же ввести их в конфиг кловера. В конце концов можно вводить ручками при загрузке клевера. Я сделал так, в nvram прописал sudo nvram boot-args="debug=0x141 kdp_match_name=en3", а при загрузке клевера дописываю kcsuffix=debug если надо попасть в отладочное ядро или ничего не добавляю и гружусь в release ядро.
    7. Перезагружаемся и дожидаемся остановки ядра. При выставленных опциях в ключе debug отладку можно делать с любой машины из сети. Я отлаживаю через ноутбук по WiFi.
     

    Вложения:

    Последнее редактирование: 21 янв 2017
    nms42, Moorre, Sergey_Galan и 3 другим нравится это.
  19. vit9696

    vit9696 Apple Life Dev Разработчик

    Симпатии:
    1`436
    @RemB, отлично! Добавил ссылку на пост в шапку. По поводу патчей кловера, если после проверки подтверждается, что работает, @slice, добавишь в транк?
     
    Moorre и chrome нравится это.
  20. slice

    slice Apple Life Dev Разработчик

    Симпатии:
    8`029
    Без проблем. Вопрос следующий. Это патч для конкретной версии debug ядра? или есть какая-то универсальность?
     
    Moorre и chrome нравится это.

Поделиться этой страницей