tgoop.com/cpplastic/345
Last Update:
Вирішив спробувати написати парсер бінарного формату логів (DLT — Diagnostic Log and Trace protocol). Є, звісно, офіційна відкрита специфікація від AUTOSAR. Читати такі зазвичай вкрай неприємно — дуже сухий текст з перехресними посиланнями на реквайрменти, причому в PDF-ці це не клікабельні посилання, а тупо текстовий ідентифікатор у дужках.
Але якщо перебороти себе з читанням, то якраз імплементувати щось по таких спеках — це просто пісня. Все чітко та детально розписане — бери й транслюй у код собі.
Так я й зробив. Вирішив використовувати Kaitai Struct, про який вже згадував раніше. Формат DLT не суперскладний, але вельми обʼємний, тож нормально часу на це пішло. Потестував на парі маленьких файлів — все чудово.
А потім запускаю у їхній (локально піднятій) web IDE на більш практично-реалістичному файлі на 1,3 мільйона записів — а воно всирається десь посеред парсингу і не пише, де саме. Двійковим пошуком швидко знайшов, що відбувається це в районі 18093-го запису. Дивлюся — і не розумію. Навіть десять разів перевірив свою імплементацію.
Короч, у файлі зберігаються бінарні записи один за одним. Починається все з ["DLT", 0x1]
, далі йде storage header, standard header, опціональний extended header та payload. В пейлоді лежить довільна кількість «аргументів» різних типів: тип вказаний бітово на початку пейлода, а саме значення лежить за ним. І там вказано, що має бути unsigned int64, але лежить всього 4 байти! Ну й парсер такий: «Відмовляюся працювати далі!»
До того ж у standard header лежить загальна довжина повідомлення, і по ній чітко видно, що там саме 4 байти в кінці лишається. Але! Якщо відкрити у якійсь програмі для перегляду логів, наприклад у Chipmunk, то воно хаває файл без проблем. Як?
Виходячи з того значення, яке Chipmunk показує, виявилося, що їхній парсер (на расті до речі) тупо ігнорує загальну довжину повідомлення, а читає собі спокійнісенько 8 байтів з тієї позиції, з якої його попросили. І нічо, що друга половина — це вже початок нового повідомлення
Але головне питання тут не до Chipmunk. Я щось просто не второпаю, як можна було записати такий файл. Може й тупо баг, звісно, і там мав бути uint32
, а не uint64
, але трясця — тут же навіть думати не сильно треба було: маючи спеку, просто йдеш по ній, пишеш код, а потім пишеш тести, бо в специфікації всі реквайрменти максимально чітко прописані, де який біт має бути виставлений за яких умов. Сумно якось це все трохи
P.S. До речі, у процесі ще намагався використовувати ImHex, про який теж згадував, але при написанні власних патернів він крашить що курва. Неможливо користуватися взагалі.