web-dev-qa-db-fra.com

Comment déboguez-vous un format binaire?

J'aimerais pouvoir déboguer la construction d'un générateur binaire. En ce moment, je suis en train d'imprimer les données d'entrée sur l'analyseur binaire, puis d'aller en profondeur dans le code et d'imprimer le mappage de l'entrée sur la sortie, puis de prendre le mappage de sortie (entiers) et de l'utiliser pour localiser l'entier correspondant dans le binaire. Assez maladroit, et nécessite que je modifie profondément le code source pour obtenir le mappage entre l'entrée et la sortie.

Il semble que vous puissiez voir le binaire dans différentes variantes (dans mon cas, je voudrais le voir en morceaux de 8 bits sous forme de nombres décimaux, car c'est assez proche de l'entrée). En fait, certains nombres sont 16 bits, certains 8, certains 32, etc. Il y aurait donc peut-être un moyen de visualiser le binaire avec chacun de ces différents nombres mis en évidence en mémoire d'une manière ou d'une autre.

La seule façon dont je pouvais voir que cela était possible était de créer un visualiseur spécifique au format/disposition binaire réel. Il sait donc où dans la séquence les numéros 32 bits devraient être, et où les numéros 8 bits devraient être, etc. C'est beaucoup de travail et un peu délicat dans certaines situations. Je me demande donc s'il y a une façon générale de le faire.

Je me demande également quelle est la façon générale de déboguer ce type de chose actuellement, alors peut-être que je peux avoir des idées sur ce qu'il faut essayer.

11
Lance Pollard

Pour les vérifications ad hoc, utilisez simplement un hexdump standard et apprenez à le regarder.

Si vous voulez vous outiller pour une enquête appropriée, j'écris généralement un décodeur séparé dans quelque chose comme Python - idéalement, cela sera piloté directement à partir d'un document de spécification de message ou IDL, et sera aussi automatisé que possible (il n'y a donc aucune chance d'introduire manuellement le même bug dans les deux décodeurs).

Enfin, n'oubliez pas que vous devez écrire des tests unitaires pour votre décodeur, en utilisant une entrée fixe connue.

76
Useless

La première étape pour ce faire est que vous avez besoin d'un moyen de trouver ou de définir une grammaire qui décrit la structure des données, c'est-à-dire un schéma.

Un exemple de ceci est une fonction de langage de COBOL qui est officieusement connue sous le nom de copybook. Dans les programmes COBOL, vous définiriez la structure des données en mémoire. Cette structure correspondait directement à la façon dont les octets étaient stockés. Ceci est commun aux langages de cette époque par opposition aux langages contemporains courants où la disposition physique de la mémoire est un problème d'implémentation qui est éloigné du développeur.

Une recherche Google pour langage de schéma de données binaires fait apparaître un certain nombre d'outils. Un exemple est Apache DFDL . Il peut également y avoir une interface utilisateur pour cela.

10
JimmyJames

ASN.1 , Notation de syntaxe abstraite numéro un, permet de spécifier un format binaire.

  • DDT - Développez en utilisant des exemples de données et des tests unitaires.
  • Un vidage textuel peut être utile. Si en XML, vous pouvez réduire/développer les sous-hiérarchies.
  • ASN.1 n'est pas vraiment nécessaire mais une spécification de fichier basée sur la grammaire et plus déclarative est plus facile.
6
Joop Eggen

D'autres réponses ont décrit la visualisation d'un vidage hexadécimal ou l'écriture de structures d'objets dans JSON. Je pense que combiner les deux est très utile.

L'utilisation d'un outil qui peut rendre le JSON au-dessus du vidage hexadécimal est vraiment utile; J'ai écrit un outil open source qui analysait les binaires .NET appelé dotNetBytes , voici un vue d'un exemple de DLL .

dotNetBytes Example

3
Carl Walsh

Je ne suis pas sûr de bien comprendre, mais il semble que vous ayez un analyseur pour ce format binaire et que vous en contrôliez le code. Donc, cette réponse est construite sur cette hypothèse.

Un analyseur remplira en quelque sorte les structures, les classes ou toute autre structure de données de votre langage. Si vous implémentez un ToString pour tout ce qui est analysé, vous vous retrouvez avec une méthode très facile à utiliser et facilement gérée pour afficher ces données binaires dans un format lisible par l'homme.

Vous auriez essentiellement:

byte[] arrayOfBytes; // initialized somehow
Object obj = Parser.parse(arrayOfBytes);
Logger.log(obj.ToString());

Et c'est tout, du point de vue de son utilisation. Bien sûr, cela vous oblige à implémenter/remplacer la fonction ToString pour votre classe/struct/$ Object, et vous devrez également le faire pour toutes les classes/structures/whatevers imbriquées.

Vous pouvez également utiliser une instruction conditionnelle pour empêcher la fonction ToString d'être appelée dans le code de version afin de ne pas perdre de temps sur quelque chose qui ne sera pas enregistré en dehors du mode débogage.

Votre ToString pourrait ressembler à ceci:

return String.Format("%d,%d,%d,%d", int32var, int16var, int8var, int32var2);

// OR

return String.Format("%s:%d,%s:%d,%s:%d,%s:%d", varName1, int32var, varName2, int16var, varName3, int8var, varName4, int32var2);

Votre question d'origine donne l'impression que vous avez quelque peu tenté de le faire et que vous pensez que cette méthode est lourde, mais vous avez également à un moment donné implémenté l'analyse d'un format binaire et créé des variables pour stocker ces données. Il vous suffit donc d'imprimer ces variables existantes au niveau d'abstraction approprié (la classe/structure dans laquelle se trouve la variable).

C'est quelque chose que vous ne devriez faire qu'une seule fois, et vous pouvez le faire tout en construisant l'analyseur. Et cela ne changera que lorsque le format binaire changera (ce qui entraînera déjà une modification de votre analyseur).

Dans la même veine: certains langages ont des fonctionnalités robustes pour transformer des classes en XML ou JSON. C # est particulièrement bon dans ce domaine. Vous n'avez pas à abandonner votre format binaire, vous faites simplement le XML ou JSON dans une instruction de journalisation de débogage et laissez votre code de version seul.

Je recommanderais personnellement de ne pas emprunter la route de vidage hexadécimal, car elle est sujette à des erreurs (avez-vous commencé sur le bon octet, êtes-vous sûr lorsque vous lisez de gauche à droite que vous "voyez" l'endianness correcte, etc.) .

Exemple: dites que vos ToStrings crachent des variables a,b,c,d,e,f,g,h. Vous exécutez votre programme et remarquez un bogue avec g, mais le problème a vraiment commencé avec c (mais vous déboguez, donc vous ne l'avez pas encore compris). Si vous connaissez les valeurs d'entrée (et vous devriez), vous verrez instantanément que c est l'endroit où les problèmes commencent.

Par rapport à un vidage hexadécimal qui vous indique simplement 338E 8455 0000 FF76 0000 E444 ....; si la taille de vos champs varie, où commence c et quelle est la valeur - un éditeur hexadécimal vous le dira mais mon point est que cela est sujet aux erreurs et prend du temps. Non seulement cela, mais vous ne pouvez pas automatiser facilement/rapidement un test via une visionneuse hexadécimale. L'impression d'une chaîne après l'analyse des données vous dira exactement ce que votre programme "pense" et sera une étape sur la voie des tests automatisés.

1
Shaz