Chciałbym móc debugować budowanie binarnego konstruktora. W tej chwili w zasadzie drukuję dane wejściowe do parsera binarnego, a następnie wchodzę głęboko w kod i drukuję mapowanie danych wejściowych na dane wyjściowe, a następnie biorę mapowanie danych wyjściowych (liczby całkowite) i używam tego do zlokalizowania odpowiedniej liczby całkowitej w pliku binarnym. Całkiem niezręczny i wymaga głębokiej modyfikacji kodu źródłowego, aby uzyskać mapowanie między wejściem a wyjściem.
Wygląda na to, że można wyświetlić plik binarny w różnych wariantach (w moim przypadku chciałbym zobaczyć go w 8-bitowych częściach jako liczby dziesiętne, ponieważ jest to dość bliskie wartości wejściowej). W rzeczywistości niektóre liczby są 16-bitowe, niektóre 8, niektóre 32 itd. Może więc istniałby sposób, aby zobaczyć dane binarne z każdą z tych różnych liczb podświetloną w jakiś sposób.
Jedynym sposobem, w jaki mogłem zobaczyć, że jest to możliwe, jest zbudowanie wizualizatora specyficznego dla rzeczywistego formatu / układu binarnego. Więc wie, gdzie w sekwencji powinny znajdować się liczby 32-bitowe, a gdzie powinny być liczby 8-bitowe itp. W niektórych sytuacjach jest to bardzo pracochłonne i trudne. Zastanawiam się więc, czy jest na to ogólny sposób.
Zastanawiam się również, jaki jest obecnie ogólny sposób debugowania tego typu rzeczy, więc może uda mi się znaleźć kilka pomysłów na to, co można z tego wypróbować.
Odpowiedzi:
Do kontroli ad hoc wystarczy użyć standardowego zrzutu heksadecymalnego i nauczyć się go obserwować.
Jeśli chcesz przygotować się do właściwego dochodzenia, zwykle piszę osobny dekoder w czymś takim jak Python - najlepiej będzie on sterowany bezpośrednio z dokumentu specyfikacji wiadomości lub IDL i będzie możliwie najbardziej zautomatyzowany (więc nie ma szans na ręczne wprowadzenie ten sam błąd w obu dekoderach).
Na koniec nie zapominaj, że powinieneś pisać testy jednostkowe dla twojego dekodera, używając znanych poprawnych danych wejściowych.
źródło
Pierwszym krokiem do tego jest potrzeba znalezienia lub zdefiniowania gramatyki opisującej strukturę danych, tj. Schematu.
Przykładem tego jest funkcja językowa języka COBOL, która jest nieformalnie znana jako zeszyt. W programach COBOL definiowałbyś strukturę danych w pamięci. Ta struktura jest odwzorowana bezpośrednio na sposób przechowywania bajtów. Jest to typowe dla języków tamtej epoki, w przeciwieństwie do popularnych współczesnych języków, w których fizyczny układ pamięci stanowi problem implementacyjny, który jest oderwany od programisty.
Wyszukiwarka Google dla języka schematu danych binarnych ujawnia szereg narzędzi. Przykładem jest Apache DFDL . Może również istnieć interfejs użytkownika do tego.
źródło
ASN.1 , Abstract Syntax Notation One, umożliwia określenie formatu binarnego.
źródło
Inne odpowiedzi opisywały wyświetlanie zrzutu heksadecymalnego lub zapisywanie struktur obiektów np. W JSON. Myślę, że połączenie obu tych elementów jest bardzo pomocne.
Bardzo przydatne jest użycie narzędzia, które może renderować JSON na szczycie zrzutu heksadecymalnego; Napisałem narzędzie typu open source, które analizowało pliki binarne .NET o nazwie dotNetBytes , oto widok przykładowej biblioteki DLL .
źródło
Nie jestem pewien, czy w pełni to rozumiem, ale wygląda na to, że masz parser dla tego formatu binarnego i kontrolujesz dla niego kod. Ta odpowiedź jest oparta na tym założeniu.
Analizator składni będzie w jakiś sposób wypełniał struktury, klasy lub dowolną strukturę danych, którą posiada Twój język. Jeśli zaimplementujesz a
ToString
dla wszystkiego, co zostanie przeanalizowane, otrzymasz bardzo łatwą w użyciu i łatwą w utrzymaniu metodę wyświetlania tych danych binarnych w formacie czytelnym dla człowieka.Zasadniczo miałbyś:
I to wszystko, z punktu widzenia korzystania z niego. Oczywiście wymaga to zaimplementowania / przesłonięcia
ToString
funkcji dla swojejObject
klasy / struct / cokolwiek, i musiałbyś to zrobić również dla wszystkich zagnieżdżonych klas / struktur / whatevers.Możesz dodatkowo użyć instrukcji warunkowej, aby zapobiec
ToString
wywołaniu funkcji w kodzie wersji, abyś nie marnował czasu na coś, co nie zostanie zarejestrowane poza trybem debugowania.Twój
ToString
może wyglądać tak:Twoje pierwotne pytanie brzmi, jakbyś próbował to zrobić, i że uważasz, że ta metoda jest uciążliwa, ale w pewnym momencie zaimplementowałeś także parsowanie formatu binarnego i stworzyłeś zmienne do przechowywania tych danych. Wszystko, co musisz zrobić, to wydrukować istniejące zmienne na odpowiednim poziomie abstrakcji (klasa / struktura, w której znajduje się zmienna).
Jest to coś, co powinieneś zrobić tylko raz, i możesz to zrobić podczas budowania parsera. Zmieni się on tylko wtedy, gdy zmieni się format binarny (co i tak już spowoduje zmianę parsera).
Podobnie: niektóre języki mają solidne funkcje przekształcania klas w XML lub JSON. C # jest w tym szczególnie dobry. Nie musisz rezygnować z formatu binarnego, po prostu wykonuj XML lub JSON w instrukcji rejestrowania debugowania i zostaw swój kod wersji w spokoju.
Osobiście polecam nie przechodzić trasy zrzutu szesnastkowego, ponieważ jest ona podatna na błędy (czy zacząłeś od prawego bajtu, czy jesteś pewien, że kiedy czytasz od lewej do prawej, że „widzisz” prawidłową endianizm itp.) .
Przykład: Powiedz swoje
ToStrings
zmienne wypluwającea,b,c,d,e,f,g,h
. Uruchamiasz program i zauważasz błądg
, ale problem naprawdę zaczął się odc
(ale debugujesz, więc jeszcze tego nie odkryłeś). Jeśli znasz wartości wejściowe (i powinieneś), od razu zobaczysz, żec
tutaj zaczynają się problemy.W porównaniu do zrzutu heksadecymalnego, który po prostu mówi
338E 8455 0000 FF76 0000 E444 ....
; jeśli twoje pola mają różną wielkość, gdziec
zaczyna się i jaka jest wartość - edytor szesnastkowy powie ci, ale chodzi mi o to, że jest to podatne na błędy i czasochłonne. Ponadto nie można łatwo / szybko zautomatyzować testu za pomocą przeglądarki szesnastkowej. Wydrukowanie ciągu po analizie danych powie dokładnie, co twój program „myśli” i będzie jednym krokiem na drodze zautomatyzowanego testowania.źródło