Phase 13: Tools & Protocols

خارج الشفرة الأصلية: Python ، JVM ، .NET ، و WebAssembly Bytecode

ملف رمز البايت هو برنامج بالإضافة إلى ملاحظات المُحامِل حول ذلك، وهذه الدروس تُبني القراء التي تُظهر أي ملاحظات كل حاوية تحتفظ بها.

Type: Build

Languages: Python, TypeScript, Java, C#, WebAssembly text

Prerequisites: Phase 13 · 32 (ELF from scratch), 33 (disassembly and control flow)

Time: ~150 minutes

أهداف التعلم

  • اقرأ 16 بايت .pycالعنوان من PEP 552 و إزالة الرمز من الكود دون marshalالوحدة، للملفات التي كتبها أربعة إصدارات مترجم.
  • تحليل ملف فئة JVM من JVMS الفصل 4: مجموعة ثابتة، الحقول، الأساليب، Codeالصفة الثانيةjavac -gيضيف
  • تفكيك رموز JVM في Ledger.classو إثبات الإدراج ضدjavap -cعلى أربعة بناءات من نفس المصدر
  • اقرأ قسم وحدات WebAssembly قسمًا بعد قسم ، و فك كل جسم وظيفة ، و أثبت النتيجة مقابل wasm-objdump -d. . .
  • قم بتنقل البيانات المعدنية ECMA-335 من مجموعة .NET من دليل البيانات PE إلى MethodDefالصفوف و CIL لكل طريقة، والتحقق من مكتبة القارئ التي تستخدم ILSpy.
  • قياس، لعمل واحد في خمسة حاويات، أي أسماء وأنواع، وهيكل التحكم كل تنسيق يحتفظ بها والتي تفقدها.

المشكلة

لقد بنيتledger.pyووجدتledger.cpython-314.pycفي__pycache__سألت العميل ما الذي يحتوي عليه الملف، قام العميل بإجراء عملية تحليل، طبعت الأداةUnsupported opcodeوخط يقول# WARNING: Decompyle incompleteوخلص العميل إلى أن الملف قد تم التشويش عليه

الملف لم يُغمض، أول بايتين لهما2b 0e، الكلمة 3627 . هذا هو الرقم CPython 3.14 يكتب، وتوقف جداول الكود الاكتتاب في 3.13. كانت الأداة قديمة. وكيل لم يقرأ الرأس، لذلك لم يتمكن من معرفة الفرق.

دراسة 33 أظهرت ما يفقد الرمز الأصلي: أسماء المعلمات، الأنواع، والـ switchأصبح هذا طاولة قفزة حاويات رمز البايت تفقد أقل، وكل واحد يفقد شيئا مختلفا. الـ (بايك) يحافظ على كل اسم متغير ولا يوجد نوع ملف الفئة يحفظ النماذج والأسماء المحلية فقط عندما تسأل. وحدة "وازم" تحتفظ بهيكل التحكم وتسقط الأسماء ما لم يحملها قسم مخصص. يحتفظ الجمعية .NET بأسماء المعلمات في الجدول ويترك الأسماء المحلية إلى ملف منفصل. لا يمكنك تحكم في نتائج المتحلل على أي منها حتى تعرف من الملاحظات كان الحاوية لبدء.

هذه الدروس تبني أربعة قراء في مكتبة Python القياسية. كل واحد يقرأ الحاوية من أول بايت، ويرسل وظيفة واحدة، ويتم التحقق من أداة النموذج الخاصة على الأدوات التي قمت ببناءها.gradeمنledgerجنبا إلى جنب في جميع الحاويات الخمسة

الرأس هو أربعة كلمات

تعريف PEP 552 الرأس بأربعة كلمات 32 بت. الأول هو الرقم السحري. الثاني هو حقل بيت. مجموعة بيت 0 تعني الملف على أساس الهاش. مجموعة بيت 1 تعني check_source: المترجم يضغط المصدر عند الاستيراد ويقارن. مع بيت 0 واضحة، الكلمات الثالثة والرابعة هي mtime المصدر وحجم المصدر. مع مجموعة بيت 0، فإنها تحتوي على SipHash 64 بت من المصدر.

العدد السحري يعيش فيInclude/internal/pycore_magic_number.hقاعدة من 3.11 هي أن Python 3.n تبدأ عند 2900 + 50n ، وكل تغيير في رمز البايت داخل دورة الإصدار يضيف واحد. الوهم المخزن هو رقم 16 بت متبوعا\r\n3،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،

الأجهزة تحتوي على ملفات بيك لكل مترجمcompile_pyc.pyكتبهم معpy_compile.compile(..., dfile="ledger.py")حتى يكون اسم الملف المحفوظledger.pyوليس مسار آلة البناء أول 16 بايت من الملفات 3.14:

output
checked-hash   2b 0e 0d 0a  03 00 00 00  c7 16 c7 fc c5 1d 81 01
timestamp      2b 0e 0d 0a  00 00 00 00  8d 60 cf 6a  f1 01 00 00

اقرأ رأس العلامة الزمنية كلمة بعد كلمة03 00 00 00أو00 00 00 00هو كلمة العلم8d 60 cf 6aهو 0x6acf608d = 1791975565, mtime من ledger.pyعندما تم بناء الملفf1 01 00 00هو 497، حجم المصدر. الملف المحقق من الهاش يحمل العلامات 3 وثمانية بايتات الهاش بدلا من ذلك. يوافق المترجمون الأربعة على كل شيء في العنوان باستثناء الكلمة السحرية:

InterpreterMagic bytesWordFile bytesgrade.co_code bytesgrade instructions
3.11.14a7 0d 0d 0a349510548031
3.12.12cb 0d 0d 0a35319376226
3.13.12f3 0d 0d 0a35719437026
3.14.62b 0e 0d 0a36279659635

read_pyc_header()فيcode/main.pyيعيد هذه الحقول ويعطي الاسم للنسخة من الكلمة. importlib.util.MAGIC_NUMBERيعطي نفس أربعة بايتات للمترجم الجاري. python3 code/main.py compareيجمع المصدر مع كل python3.11إلىpython3.15وجدت علىPATHلكل منها يطبع الرأس الذي يراه قارئنا بجانب الحقائق التي يبلغ عنها المترجم عن نفسه

مارشال يكتب الرمز موضوع الحقل حسب الحقل

البايت 16 من كل جهاز هو e3هذا هو0x80 | ord('c'): رمز النوع المرجعي لشيء رمز مع FLAG_REFمجموعة، التي تخبر القارئ لتذكر الكائن لاحقا rالمرجحات. الوثائق المرجعية تقول أن النموذج غير مُوثق بشكل متعمد وأن كود الأشياء غير متوافقة بين الإصدارات. كلاهما صحيحان، والنموذج لا يزال صغيرًا بما فيه الكفاية للقراءة. Python/marshal.cيصف رموز النوع: Nلا أحدiإدخال 32 بت، sالبايتاتzوZسلسلة ASCII قصيرة(و)أضعافcكائن رمزي، rإشارة خلفية، يحجز الحاويات مساحة الإشارة أمام أطفالهم، لذا يقوم القارئ بنفس الشيء.

w_complex_object()يكتب كود كائن في ترتيب ثابت. بالنسبة 3.11 إلى 3.15 هو argcount،posonlyargcount،kwonlyargcount،stacksize،flagsبـ 32 بت، ثم code،consts،names،localsplusnames،localspluskinds،filename،name،qualnameكجسام، ثم firstlineno، ثمlinetableوexceptiontable. فك رمز الوحدة كود كائن ملف 3.14 يدويا من بايت 17:

output
00 00 00 00   argcount 0
00 00 00 00   posonlyargcount 0
00 00 00 00   kwonlyargcount 0
01 00 00 00   stacksize 1
00 00 00 00   flags 0
f3 22 00 00 00   type 's' with FLAG_REF, 34 bytes of co_code follow
80 00  52 06  74 00  52 01  17 00  74 01 ...

إن بايتات الرمز اثنان لكل تعليم: 80 00هوRESUME 0،52 06هوLOAD_CONST 6،74 00هوSTORE_NAME 0و17 00هوMAKE_FUNCTION. في القائمة 3.14 في الأجهزة الطباعة نفس البيانات الخمسة على مستوى الوحدة. بعد codeيأتي الثابتات، التي تحتوي على أربعة كائنات رمزية مستوى، وبعد ذلك names: ('LABELS', 'percent_change', 'grade', 'total', 'grade_label'). . .

Unmarshallerفيcode/main.pyيقرأ هذا التخطيط والقديم الذي استخدم 3.9 و 3.10، حيث nlocals،varnames،freevarsوcellvarsكانت حقل منفصلة.CodeObjectمع نفس أسماء الصفات التي يمتلكها الكائن الحقيقي.varnamesالصفائحlocalsplusnamesمن قبلCO_FAST_LOCALقليلاًlocalspluskinds- لأجلgradeفي كل ملف من الملفات الأربعة التي يعود بها('score', 'bucket')،firstlineno10، و غير فارغ linetable- الاختبارtest_unmarshaller_agrees_with_the_running_interpreterيُقارن كل مجال معmarshal.loads()الملفات الثلاثة الأخرى يمكن قراءتها بواسطة رمزنا وغير يمكن قراءتها بواسطةmarshalتحت هذا المترجم.

أربعة مترجمين، أربعة رمزات للاستعراض

يحتوي المستندات المزيفة على تحذير واحد على كل نسخة: رمز البايت هو تفاصيل تنفيذ CPython ولا يوجد ضمان بأن يبقى نفسه.python3.1N -m dis ledger.pyتم التقاط كل مترجم

في 3.11 gradeيبدأ هكذا:

output
 11           2 LOAD_FAST                0 (score)
              4 LOAD_CONST               1 (10)
              6 BINARY_OP                2 (//)
             10 STORE_FAST               1 (bucket)
 12          12 LOAD_FAST                1 (bucket)
             14 LOAD_CONST               2 (9)
             16 COMPARE_OP               5 (>=)
             22 POP_JUMP_FORWARD_IF_FALSE     2 (to 28)

BINARY_OPيقع في التفاصيل 6 والإرشاد التالي في 10. البايتين بينهم هو مدخل مخزن مخزن داخلي من PEP 659، المترجم التكيفي المتخصص. COMPARE_OPفي 16 يلي 22، لذلك هو يمتلك إدخالات مخزن اثنين.show_caches=True. 3.12 يبدل LOAD_CONSTبالإضافةRETURN_VALUEمعRETURN_CONST, تغيير اسم القفز إلى POP_JUMP_IF_FALSEو يختصرونgradeمن 80 إلى 62 بايت. 3.13 طباعة العلامات L1إلىL4بدلا من تعويضات وتعطى CLI -Cلخزائن الاحتياطي و-Oلتحويلات. 3.14 إزالة RETURN_CONSTمرة أخرى، يضيف LOAD_SMALL_INTوLOAD_FAST_BORROW، و إدخالات NOT_TAKENبعد كل قفزة مشروطة:

output
 12         20       LOAD_FAST_BORROW         1 (bucket)
            22       LOAD_SMALL_INT           9
            24       COMPARE_OP             188 (bool(>=))
            26       CACHE                    0 (counter: 0)
            28       POP_JUMP_IF_FALSE        3 (to L1)
            30       CACHE                    0 (counter: 0)
            32       NOT_TAKEN
  • نعم-C -Oالعروض المدرجة 13 CACHEإدخالات داخل grade: بعد خمسةBINARY_OP، واحد بعد كل واحدCOMPARE_OP، واحد بعد كل واحدPOP_JUMP_IF_FALSE.الجهاز التكيفي يظهر ما هي الاكشافات .بعد 200 مكالمةdis.dis(grade, adaptive=True)بصماتRESUME_CHECKوCOMPARE_OP_INTحيث كان الإدراج المُباشرRESUMEوCOMPARE_OPوtotalتظهرFOR_ITER_LIST،BINARY_OP_ADD_INTوJUMP_BACKWARD_NO_JIT. الأشكال المتخصصة تعيش في نفسco_codeالبايتات. لم يحتوي جهاز الكمبيوتر على هذه البايتات أبداً، لأن التخصص يحدث في الذاكرة.

هذا هو السبب في أن المفكّرات لديها سقف إصدار. uncompyle6 3.9.3 تقول أنها تقبل رمز البايت من Python 1.0 إلى 3.8. decompyle3 3.9.3 يقرأ 3.7 و 3.8. xdis 6.3.0, وقطع الإصدارات المتقاطعة وراء كل منهما، يقرأ إلى 3.13. pycdc لديه جداول رمز الاختيار حتى python_3_13.cppفي ملف بناءها، وعلى طبعات رمز opcode مجهولة Unsupported opcodeويشير الملف إلى أن النتائج غير كاملة. يطالب PyLingual بكل إصدار صدر منذ 3.6 ويستخدم مترجمين من 3.8 إلى 3.15 لإعادة تجميع وتحقق من النتائج الخاصة به. بالنسبة لملف 3.14، فإن الثلاثة الأولى ترفض أو تفشل، ولا تنطبق إلا الأخيرتين. اقرأ الكلمة السحرية قبل اختيار أداة.

ملف الفئة يحافظ على قاموسه

في JVMS Java SE 25، القسم 4.1، يقدم التخطيط كهيكل واحد: magic،minor_version،major_version،constant_pool_count, المسبح المستمر ,access_flags،this_class،super_class، واجهات ، حقل ، طرق ، صفات السحر هو0xCAFEBABE. يقبل جهاز جاوا SE 25 الافتراضي الإصدارات الرئيسية 45 إلى 69، ويعتبر أقل من 65535 ملفًا من ميزة المشاهدة المسبقة.Ledger-g.classهل هيca fe ba be 00 00 00 41 00 5e: الرئيسية 65 هو جاوا 21 و 0x5e= 94 هو عدد المجموعة المستمرة. Ledger-jdk25.class، تم بناؤه بواسطة javac 25.0.2 من نفس المصدر، يبدأ ca fe ba be 00 00 00 45الرئيسي 69

المجموعة المستمرة هي حيث يحتفظ ملف الفصل قاموسه الخاص.#13في-gالبناء هوMethodrefهذا يشير إلى الصف#8و الاسم و النوع#14. تتبع المؤشرات يعطيLedger.grade:(I)I، والذي هو بالضبط ماjavap -vبصمات بعد//. وصف(I)Iهو واحدintالمعلم وintالنتيجة([I)Iعلىtotalيقول أن المعلم هوintالمصفوفة. كل طريقة، وحقل، والفئة التي يلمسها الرمز له مثل هذا الإدخال، والتحقق في القسم 4.10 يرفض الملف الذي لا يوافق مع تعليماتها.ClassFileالفصل فيcode/main.pyيقرأ جميع علامات الثابتة الـ 17 من الجدول 4.4 ويعالجLongأوDoubleيرتفع على علامة مجهولة وعلى البايتات بعد الصفحة الأخيرة

الصفات تعتمد على الفئة، كل حقل، كل طريقة، وال Codeسمة نفسها. يقول JVMS أن الآلة الافتراضية يجب أن تتجاهل الصفات التي لا تعرفها ، ولهذا السبب يمكن إضافة جداول التحليل أو إسقاطها دون تغيير جسم طريقة. دليل javac يقول -gيُولد كل معلومات التحليل بما في ذلك المتغيرات المحلية، أن الإعداد الافتراضي يُولد أرقام الخط والملف المصدر فقط، وأن -g:noneلا يخلق شيئاً، الثلاثة يبني مقياساً

BuildBytesConstant pool countLineNumberTableLocalVariableTableSourceFilegrade code bytes
javac -g1832947 methods6 methodsyes50
javac1581827 methodsnoneyes50
javac -g:none140479nonenoneno50

50 بايت رمزية من gradeويتم التحقق من ذلك-gيضيف لgradeهو واحدLocalVariableTableالصف: بداية 0، طول 50، فتحة 0، اسم score، وصفIبدونها ، فالمُفكّر يرى فتحة 0 من النوعintو يجب أن يختلق اسمًاStackMapTableيبقى في كل بناء لأن المؤكد يحتاجه، وال BootstrapMethodsالصفحة تبقى لأن mainيُحدد الخيوط عبر invokedynamic. . .

فك تشفير المفاتيح من خلال اليد

يحدد الفصل 6 من JVMS كل تعليمات بايت واحد opcode والعمليات التي تسمي opcode. تعادلات الفرع هي قيم مؤكدة 16-bit بالنسبة إلى عنوان الفرع opcode، والتي تختلف عن x86-64, حيث التحول بالنسبة إلى التعليمات التالية. tableswitchوlookupswitchتبدأ مع صفر إلى ثلاثة بايتات التشغيل بحيث تبدأ أوبراندها 32-بيت من عنوان هو مضاعف أربعة.

البايتات من gradeمن حاسوب 4 في Ledger-g.class:

output
aa                 tableswitch at pc 4
00 00 00           padding to pc 8
00 00 00 2c        default: 4 + 44 = 48
00 00 00 06        low 6
00 00 00 0a        high 10
00 00 00 2a        case 6:  4 + 42 = 46
00 00 00 28        case 7:  4 + 40 = 44
00 00 00 26        case 8:  4 + 38 = 42
00 00 00 24        case 9:  4 + 36 = 40
00 00 00 24        case 10: 4 + 36 = 40

36 بايت، تعليمات واحدة، والكلswitch (score / 10)مع قضيتها المشتركة ل 9 و 10.switchفي الدروس 33 كان يحتاج إلى فحص الحدودlea، أmovslq، وaddهنا الأهداف في التعليمات، وكذلك حقيقة أنهم ينتمون معا.

disassemble_jvm()تغطي جميع 202 رمزًا محددًا مع عرض أوبراندها ، وتتبع قاعدة التدليك ، وتجعل أوبراندها طريقة javapنعمcompare_with_javap()يُحلل المُسجنينjavap -c -pالنص، بما في ذلك الخطوط المتعددة tableswitchكل أربعة تشكيلات تتفق على 108 من 108 تعليمات.test_branch_offsets_are_relative_to_the_branch_instructionالتحققاتifneفي pc 1 الهبوط على 6 ، if_icmpgeعند 13 الهبوط على 33 ، وgotoفي 30 الهبوط مرة أخرى على 10.

رادار2 6.2.4 ، تم بناؤه من المصدر لهذه الدروس ، يقرأ نفس الملف. rabin2 -Iتقارير arch java،lang java 21،linenum trueوlsyms true، والتي هي قراءة الإصدار والجدولين التصحيحي. pd 14 @ sym.Ledger.gradeيطبعtableswitchمع السهام إلى أهدافها الخمسة.Unable to parse code attribute: 2في هذا الملف، وهو قيود أداة أسماء نفسها وسبب للحفاظ على javapكالمعرفة. إنّ مُحللات هذا النموذج متقدمة بالمقارنة مع Python. CFR 0.152 مرخصة مع معهد ماساتشوستس للتكنولوجيا Procyon 0.6.0 و Vineflower 1.12.0 هي Apache-2.0 و Vineflower هو فرن فلور مع دعم جاوا 21. (فيرنفلور) نفسه يعيش داخل مخزن مجتمع (إنتلي جي) تغطي JADX 1.5.6 تنسيق Android DEX ، وكانت آخر إصدار JD-GUI في عام 2019. قام هاراند وسوتو فاليرو ومونبروس وبودري بقياس ثمانية منها في عام 2020. أفضل إنتاج صحيحة نحو نحو 84 في المائة من الفصول والإنتاج معادل معنويًا لـ 78 في المائة. استعاد مُحلل التلفزيونات المُتَعَدّدُ 37.6 بالمئة من الفئات التي لم تتعامل بها أداة واحدة. الأنواع والأسماء والكؤوس المحققة تجعل النموذج قابل للكمبلة. لا يُكملون أيّ مُحاميل واحد.

وحدة الجذع قائمة من القسمات

المواصفات الأساسية تعرّف الوحدة على أنها المواصلة 00 61 73 6d 01 00 00 00، السلسلة\0asmوالإصدار 1، تليها أقسام. كل أقسام هي بايت واحدu32حجم في LEB128 ومحتوياته. أرقام 1 إلى 13 هي القسمات المعروفة، كل مرة على الأكثر في الترتيب. id 0 هو قسم مخصص مع اسم، يسمح في أي مكان. جميع الأرقام الكاملة هي LEB128, لذلك e4 00هو 100 و 80 08هو 1024wasm-objdump -hعلىledger.wasmيذكر سبع أقسام، وWasmModuleيجد نفس السبع مع نفس تعويضات الحمولة المفيدة:

SectionPayloadCountWhat it holds for ledger
Type10 to 263(i32) -> nil, (i32, i32) -> i32, (i32) -> i32
Import28 to 391env.log with type 0
Function41 to 464type index for each defined function
Memory48 to 511one page, no maximum
Export53 to 1105memory and the four function names
Code113 to 2714bodies of 23, 63, 44, and 23 bytes
Data273 to 2901F\0D\0C\0B\0A\0 at offset 1024

توجد فصل بين أجزاء الوظيفة والرمز بحيث يمكن للمتنشر أن يبدأ في تجميع قبل وصول الملف بأكمله. كل إدخال رمز هو حجم، ومركز من الإعلانات المحلية، والتعبير.gradeالمتجه المحلي هو01 7f: مجموعة واحدة من واحد i32هذا هوbucket، مع نوعها ودون اسمه

تدفق التحكم هو مهيكل من خلال البناء.block،loopأوifالمكونات. يتم تحديد العلامات حسب عمق العشب. br_tableيقوم بإجراء فرع غير مباشر من خلال جهاز عمل يُصفف قائمة العلامات.gradeفي تعويض الملفات0xa3:

output
0e                  br_table
0b                  11 labels follow
04 04 04 04 04 04   buckets 0 to 5: label 4, the outermost block, returns 0
03 02 01 00         buckets 6, 7, 8, 9: labels 3, 2, 1, 0
00                  bucket 10: label 0, shared with 9
04                  default label 4

كل ملصق هو عمق.block، والرقم بعدendهوi32.const 4يليها br 4خارج حجر النتيجة.blockالتعليمات أمام الطاولة، والعشرة علامات، والخمسة brالتعليمات بعد أن يكون كله switchويقوم المحقق بتجاهل أي فرع يغادر الهيكلdisassemble_wasm()تتبع العمق حتى الرسومات المدرجة مثل wasm-objdump، تغطي كل رمز خيار واحد من unreachableإلىi64.extend32_s، و يطابق الاعتقالاتwasm-objdump -dعلى 77 من 77 تعليمات لكل من البنايات.

الأسماء هي الشيء الوحيد الذي يُسقطه الوحدة العاديةwasm-objdumpبصمات مستمرة<grade>لأن قسم التصدير يقوم بتخريط تلك السلسلة إلى مؤشر الوظيفة 2 ، والقارئ يفعل الشيء نفسه. الأسماء المحلية لا توجد في أي مكان في الملف البايت 290. wat2wasm --debug-namesيضيف قسمًا مخصصًا يسمى nameمع الفرق الفرعية لسم الوحدة، أسماء الوظائف، والأسماء المحلية. النظام الملف ينمو إلى 425 بايت. القارئ يجد {0: 'score', 1: 'bucket'}للعمل 2 و {0: 'values', 1: 'count', 2: 'sum', 3: 'i'}للعمل 3. wasm-stripيزيل القسم مرة أخرى. مخزن الاتفاقيات الأداة يصف اثنين من المحاملين. يمكن دمج DWARF على النحو.debug_*القسمات المخصصة.sourceMappingURLيمكن أن يشير القسم المخصص إلى خريطة مصدر أعداد العمود هي تعويضات بايت إلى الثنائي.

أدوات تحرك خلال عام 2026، وبت 1.0.42، أصدرت في عام 2026-09-15, تم إزالتهاwasm-decompileو المُبني على هذه الآلة لديه بالضبط الأدوات الـ11 المتبقيةprint،objdumpوdemangle. إصدار (بيناريان)_133 يقدم wasm-dis. رادار2 6.2.4 يقرأ الوحدة أيضاً.rabin2 -Iيقولarch wasm. رمزها لـgradeيبدأ في0x8e، حيث يبدأ متجه المحليين، بينما wasm-objdumpتسمية الوظيفة في 0x8bحيث تبدأ حقل الحجم.get_local،set_localوbrtable 11 4 4 ...مع طباعة عدد العلامات البايتات هي نفسها في كل الأدوات الثلاثة وتختلف التكليف، لذلك يجب أن يكون المقارنة اسم الأداة التي تم التقاطها بها. البحث لهذا الدروس لم يجد أي وحدات معالج WebAssembly في دليل معالج Ghidra، ولم يتم قراءة هذا القائمة بالكامل. إنّ مُبنى Ghidra-wasm-plugin v2.4.0 من طرف ثالث يستهدف Ghidra 12.0. المواصفات نفسها هي وثيقة حية واحدة. صفحة W3C للwasm-core-2هو مشروع توصية المرشحين المؤرخ 13 أكتوبر 2026 الذي يصف ملخصه الإصدار 3.0، ومشروع المحررين يحمل نفس التاريخ.

البيانات المعدنية ECMA-335 هي قاعدة بيانات البرنامج الخاصة

مجموعة .NET هي ملف PE. LedgerNet.dllيبدأ بـMZ، لديه ثلاثة أقسام اسمها.text،.rsrcو.reloc، ويقول آلة0x14cلأن المجمع أصدرت رمز محايد المنصة. دليل البيانات 14 من الرأس الاختياري، الرأس CLR Runtime، يشير إلى RVA 0x2008. ECMA-335 II.25.3.3 تعريف 72 بايت هناك:

output
48 00 00 00   Cb 72
02 00 05 00   MajorRuntimeVersion 2, MinorRuntimeVersion 5
78 21 00 00   MetaData RVA 0x2178
84 07 00 00   MetaData size 1924
01 00 00 00   Flags: COMIMAGE_FLAGS_ILONLY
05 00 00 06   EntryPointToken 0x06000005, MethodDef row 5, which is Main

جذور البيانات المعدنية في RVA 0x2178يبدأ بالتوقيع42 53 4a 42، والتي تقرأBSJB، ثم النسخة 1.1 والسلسلة v4.0.30319خمسة رؤوس التيار تتبع:#~في التكافؤ0x6c، ثم#Strings،#US،#GUIDو#Blob. II.24.2 يقول كل نوع من التيارات تحدث مرة واحدة على الأكثر.#~التيار يبدأ بـHeapSizesبايت، صفر هنا، لذلك كل سلسلة، GUID، ومرجع البقع هو 2 بايت واسع، و 64 بت Validالقناع الذي يسمي الجداول المحتلة. يتم تعيين 14 قطعة:

TableIdRowsRow sizeWhat the rows say
Module0x00110the module name and its GUID
TypeRef0x01216System.Object, System.Console, 19 more
TypeDef0x02414<Module>, Ledger, and two compiler helpers
Field0x0426Labels and a static array initialiser
MethodDef0x06614the five methods and .cctor
Param0x0856before, after, score, values, score
MemberRef0x0a16612 attribute constructors and the 4 methods that Main calls
CustomAttribute0x0c126attributes the compiler and the SDK add
StandAloneSig0x1132the three local variable signatures
Assembly, AssemblyRef, ClassLayout, FieldRva, NestedClass1, 2, 1, 1, 1identity, references, layout

لا يتم تخزين حجم الصف في أي مكان. يعطي II.22 لكل عمود نوعاً، و II.24.2.6 يعطي قاعدة الحجم. مؤشر كومة هو بثنين أو أربعة بايتات من HeapSizes. مؤشر الجدول البسيط هو بثنين بايت بينما يكون هذا الجدول أقل من 65536 سطر. مؤشر مدمج يمكن أن يشير إلى n جداول مع ب بيتات علامة هو بثنين بايت بينما كل من هذه الجدول لديها أقل من 2^(16-b) الصفوف. CliAssemblyيحسب حجم 14 صف من هذه القواعد ويعد الصف. النظام.التفكير.مدونة البيانات المعدنية في الأجهزة الإصدارية تقرير نفس الحجم و نفس تعويضات الجدول، وهذا هو كيفية إثبات الاختبار الحساب.

يحدد III.1.9 الرمز: البايت العالي هو الجدول، والبايت الثلاثة المنخفضة هي الصف القائم على 1. 0x06000002هوMethodDefالصف 2 . هذا الصف لديه RVA 0x2060اسمكGrade، وقطعة توقيع00 01 08 08: الاتفاقية الافتراضية للاتصال، معايير واحدة، العودة int32، المعلمint32. إنهParamListالنقاط في الصف 3 من Param، اسمهاscoreطاولة " بارام " هي سبب إمكانية طباعة " إيلسبي "Grade(int score)من إطلاق منشأة منقطعة.0x2060يبدأ جسم المنهج بالرأس الدهني:

output
13 30         flags 0x13: fat, init locals; size 3 dwords
02 00         MaxStack 2
2d 00 00 00   CodeSize 45
01 00 00 11   LocalVarSigTok 0x11000001

StandAloneSigالصف 1 يحتفظ07 01 08: LOCAL_SIG، محلي واحد ،int32. المحلية لديها نوع وليس اسم. ECMA-335 تحتفظ بأسماء محلية في شكل إصلاح تبادل القسم V، و .NET SDK يكتبها إلى PDB. تم بناء هذا الجهاز مع DebugTypeلا يوجد أي طاولة ولا ملف يحمل اسمbucket. .PercentChangeلديه رأس صغير بدلاً من ذلك: أول بايت3aهو0x0e << 2 | 2، جسم 14 بايت بدون محليين و كومة افتراضية من 8.

45 بايت رمزية من Gradeفك الرمز مع جدول الشفرات المشتركة في القسم الثالث. switchهو رمز الاختيار0x45يليها u32العد والكثير من ذلكint32الأهداف المتعلقة بالمرشد بعد الجدول:

output
IL_0000: 02           ldarg.0
IL_0001: 1f 0a        ldc.i4.s 10
IL_0003: 5b           div
IL_0004: 0a           stloc.0
IL_0005: 06           ldloc.0
IL_0006: 1c           ldc.i4.6
IL_0007: 59           sub
IL_0008: 45 05 00 00 00 08 00 00 00 06 00 00 00 04 00 00 00 02 00 00 00 02 00 00 00
                      switch (IL_0029, IL_0027, IL_0025, IL_0023, IL_0023)
IL_0021: 2b 08        br.s IL_002b
IL_0023: 1a 2a        ldc.i4.4, ret

المحمول خصم 6 قبل switch، لذا الحالة 6 هي الهدف الأول.disassemble_cil()يعطي الرموز عبر الجداول: ldsfld Labels،call Grade،call System.Console::WriteLineوldstr ' 'من#USالمُتَكَلُّمُ لكلّ هذا هوMetaDump، برنامج C# قصير في الأجهزة المبنية علىSystem.Reflection.Metadataيطبخ عدد الصفوف، وحجم، وتعويض كل طرق، و RVA كل التوقيع، أسماء المعلمات، و بايت IL، و 226 حقل من System.Reflection.Emit.OpCodes. .compare_with_metadump()يوافق على جميع الشيكات 246 . الجدول الزمني لديه 218 رمزات إضافة إلى ثمانيةprefixالمشاركين في الجدول الدراسي يحتوي على 219 إدخالًا لأنه يحتوي علىno.من III.2.2 ، التي لم يكن لها جدول إصدار.

أدوات للصيغة: ILSpy 11.0 (MIT ، أصدرت 2026-08-12) تعمل على macOS من خلال إعداد سطح المكتب Avalonia. ilspycmd11.1.0.9782 طباعة IL مع -ilو يختار طريقة من خلال الوهم مع -m 0x06000002. dnSpyEx 6.6.0 يستمر dnSpy على Windows فقط.ildasmالسفن كحزمة NuGet بدلا من داخل SDK. radare2 6.2.4 يقرأ البيانات المعدنية أيضا: rabin2 -Iيقولarch cilوclass PE32وisالقوائمLedger.Grade(int:score):intمع اسم المعلمات وكلاهما من النوعين المأخوذة من الجداول المعلمية والتوقيع. ليس لديها إزالة CIL في هذا البناء. تم بناء هذا الإصلاح مع .NET SDK 8.0.205 لأن هذا هو SDK مثبت على آلة البناء. .NET 10 كان حاليا منذ 2025-11-11 ويكتب نفس الهياكل ECMA-335 .

ما تحتفظ به كل حاوية

ضعgradeمن كل الحاويات الخمسة في طاولة واحدة. كل سطر يأتي منpython3 code/main.py keeps، الذي يُشغل القراء على الأجهزة:

ContainerBody bytesFunction nameParameter namesParameter and return typesLocal namesLine numbersControl flow
ELF object, clang -O0118grade in .symtabnonenonenonenone, no .debug_* sections5 jumps and 1 indirect jump through a relocation table
CPython 3.14 pyc96co_qualnamescorenonebucketco_linetable, first line 104 compare and POP_JUMP_IF_FALSE pairs
JVM class, javac -g50constant poolscore in LocalVariableTable(I)Inone beyond the parameterLineNumberTable, 6 rows1 tableswitch
WebAssembly63Export sectiononly with a name section(i32) -> i32only with a name sectionnone6 nested blocks, 1 br_table, 4 br
.NET assembly45MethodDefscore in Paramstatic int32(int32)none, types only in StandAloneSignone without a PDB1 switch, 1 br.s

الجدول يشرح نتائج تحليل الملفات التي ستراها.int total(const int *, int)معint total(long param_1, uint param_2)أن Ghidra استنتج من الرمز الأصلي، لأن الرمز الأصلي لا يحفظ أي من هذه العمودات. يحتفظ Pyc كل الاسم ولا أي نوع، وتدفق التحكم هو القفزات التي تتغير شكلها كل إصدار، لذلك يقوم مفكّر Python بقطع كل نسخة واسترداد الأسماء مجانا.-gهو على، ويُعبر عنswitchوحدة "الغص" تبقي الهيكل من خلال البناء، لذاwasm2watهو رحلة ذهاب وإياب بدون خسائر والخسارة الوحيدة هي الأسماء. مجموعة .NET تحتفظ بالوصف الأكثر اكتمالاً، لأن الجداول البيانات المعدنية هي قياسية، ولا تزال بحاجة إلى PDB لاسم محلي.

يخبرك الجدول ما كان على المتحلل العمل معه ، ومع أي من نتائجها نسخ حقيقة مخزنة ومع أي إستنتاج. اسم المعلم في إرسال ILSpy هو نسخة. اسم محلي في نفس الإنفاذ هو استنتاج ما لم يكن PDB موجودًا. تدرسة 35 تسجل هذا الفرق كسلطة لكل ادعاء.

بناءها

أطلق التجربة:

bash
cd phases/13-tools-and-protocols/43-bytecode-and-managed-formats
python3 code/main.py
npx tsx code/main.ts

إن المخرج هو تقرير JSON واحد. لكل Pyc يعطي كل من العناوين، الملف و gradeالحجم، عدد التعليمات وأسماء رمزات الاختيار من القائمة التي تم التقاطها، وما إذا كان المترجم الجاري يمكن قراءتها. لكل طبقة يقدم النسخة، الحجم، حسابات جدول التحليل، والـ javapلكل بناء من "السوم" يقدم أقسام، أنواع، وظائف، محتويات قسم الاسم، والwasm-objdumpالاتفاق. لجميعها يعطي عنوان CLI، وتدفقات، وعد صفوف الجدول، والطرق، واتفاق النظام.التفكير. البيانات المعدنية. إنه ينتهي بتبيع الجدول والقائمة من المترجمين الموجودة على PATH. . .

اقرأcode/main.pyفي هذا الترتيب:

  1. Readerيحمل الوسيط والعرض الكامل. uleb()وsleb()هذه قراءة LEB128 التي تحتاجها Wasm و .NET
  2. read_pyc_header()،UnmarshallerوPycFileاقرأوا جهاز التشغيلparse_dis_text()يقرأ المعتقلينdisالقوائم بحيث لا يحتاج المقارنة بين الإصدارات إلى أربعة مترجمين في وقت الاختبار.
  3. ClassFileيقرأ ملف الفصل و disassemble_jvm()يفكّر رمزهاparse_javap_code()وcompare_with_javap()هو التحقق من الوساطة.
  4. WasmModuleيقرأ القصص وdisassemble_wasm()يُفكّر تعبيرًا بعمقهاcompare_with_wasm_objdump()هو التحقق من الوساطة.
  5. CliAssemblyيمرون PE، رأس CLI، جذور البيانات المعدنية، التيارات، والجدولات. TABLE_SCHEMASوCODED_INDEXESهي II.22 و II.24.2.6 كمعلومات. disassemble_cil()يُفكّر الجسم وcompare_with_metadump()تحقق من ذلك.
  6. NativeObjectيقرأ ELF بما فيه الكفاية لرد الرموز الوظيفية ويأخذ الدروس 33 قائمة كنصها. what_each_keeps()وfigure_data()بناء المقارنة.

هناك خمسة أوامر أخرىpython3 code/main.py pyc FILE،class FILE،wasm FILEوdll FILEطبع الهيكل و قائمة كل وظيفة في الملف الذي تعطيه لهم. python3 code/main.py compareتجميعات ledger.pyمع كل مترجم علىPATHويقومون بطبع ما كتب كل منهم

استخدمها

استخدم القراء بهذه الترتيب على حاوية صنعتها

  1. اقرأ أول بايت و اسم النموذج ثم بايتين0d 0aهو (بيك)ca fe ba beملف الفصل، 00 61 73 6dوحدة،4d 5aمع إدراج البيانات 14 وضع الجمع.
  2. اقرأ الرأس واكتب النسخة المنتجة التي يسميها. لـ pyc التي هي الكلمة السحرية، لملف الصفحة النسخة الرئيسية، لجمعة وقت تشغيل و metadata نسخة السلاسل.
  3. تحقق من كل جهاز إزالة الكمبيوتر الذي تخططين لتنفيذه مقابل هذا النسخة قبل تشغيله، وقم بتسجيل السقف وأين توثيق الأداة.
  4. قم بتشغيل القارئ وأداة النموذج الخاصة به على نفس الملف وقارنها صف بعد صف. عدم الملاءمة هو خطأ في القارئ أو تغيير في الأداة، ويجب فهم أي من هذه الأدوات قبل أن تكون القائمة دليلًا.
  5. املأ جدول الاحتفاظ بالوظيفة التي تهتم بها، وقم بتشخيص كل حقيقة كمتحتفظ بها أو ضائعة، واطلق اسم الجدول أو الصف أو القسم الذي جاء منه.
  6. فقط بعد ذلك قراءة إصدار المتحول، وقم بتشخيص كل اسم وتكليف في ذلك كنسخة من حقيقة حفظ أو كإستنتاج.

احتفظ بملفات النص في Oracle مع الحاويات. عندما يتغير مترجم، JDK، SDK، أو نسخة wabt، اعيد بناءها مع build_fixtures.shوإعادة التقاطها، لأن القائمة المتغيرة هي جهاز متغير.

المختبر التفاعلي

المختبر A: قراءة العنوان، ثم الكود الكائن

منcodeالإرشادات، مفتوحة Python:

bash
cd phases/13-tools-and-protocols/43-bytecode-and-managed-formats/code
python3 -q

أركض

python
from main import *
pyc = load_pyc("ledger.cpython-311.pyc")
pyc.header.to_dict()
pyc.module.names
pyc.functions()["grade"].varnames
len(pyc.functions()["grade"].code)

اكتب الكلمة السحرية قبل المكالمة الأولى ثم قم بتحميلledger.cpython-314.pycو قم بتقارن الاثنينcodeثم حاولimport marshal; marshal.loads(pyc.data[16:])في الملف 3.11 تحت مترجمك وقرأ الخطأ.

المختبر ب: سلسلة المسبح المستمرة

python
cls = load_class("Ledger-g.class")
cls.constant(13)
cls.constant(14)
cls.describe_constant(13)
[row["text"] for row in jvm_listing(cls, "grade")]

اتبع#13إلى#8و#14، ثم إلىUtf8الإدخالات، يدوياً قبل الاتصالdescribe_constant- ثم تحميلLedger-gnone.classو اتصلcls.method("grade").attribute_names()على كليهماCodeالمجموعة هي نفسها، والخصائص ليست كذلك.

المختبر (ج): عمق وملفات

python
module = load_wasm("ledger.wasm")
[(row["depth"], row["text"]) for row in wasm_listing(module, "grade")]
module.function_name(2)
load_wasm("ledger-names.wasm").names["locals"][2]

إبحث عنbr_tableصف و اقرأ عمقها اعدendالصفوف بعد ذلك وتطابق كل واحد من أرقام اللوحة في الجدول. ثم فتح ledger.watو العثور علىblock $sixتلك العلامة 3 أسماء.

المختبر D: من الرمز إلى البايت

python
asm = load_assembly("LedgerNet.dll")
asm.method("Grade")
body = asm.method_body(asm.method("Grade")["RVA"])
body.fat, body.max_stack, body.code_size, hex(body.local_signature_token)
asm.token_text(0x11000001)
[row["text"] for row in cil_listing(asm, "GradeLabel")]

احسب تعويض الملفات من RVA 0x2060من.textعنوان القسم يدوياً و مقارنة مع asm.rva_to_offset(0x2060)إذاً انظر للأعلىasm.row(0x08, 3)و ابحث عن مكان الاسمscoreحياة

مختبر التدريب

أضف لغة مصدر خامس للمقارنة، أو حقيقة سادسة إلى الجدول.

المتطلبات:

  • اكتب وظيفة مع حلول وتغير محلي في لغة التي لديك محفز، على سبيل المثال Kotlin إلى ملف فئة أو Rust إلى وحدة Wasm. إلتزام الخروج وإدراج القائمة في النص مع القاعدة الدقيقة في build_fixtures.sh. . .
  • اجعل القارئ المتطابق يوافق على كل تعليمات القرآن. أضف رموز إضافية فقط عندما يحتاجها المكون.
  • التمديدwhat_each_keeps()مع الحاوية الجديدة، و مع حقيقة واحدة أخرى لكل حاوية: ما إذا كان الجسم يحمل طاولة استثناء أو tryالمنطقة
  • إضافة الحاوية الجديدة إلى figure_data()ويتم إعادة التأهيلsite/figures-re-43.js. . .
  • اكتب اختبار يفشل عندما يبلغ القارئ عن حقيقة كما تم حفظها دون تسمية الجدول أو الصفة أو القسم الذي يحتوي عليها.

النجاح يعنيpython3 code/main.py keepsيظهر الصف الجديد مع أدلة لكل خلية، وكل مقارنة في النبي صلى الله عليه وسلم لا تزال توافق.

درساً أساسياً

هذا الدروس يتضمنoutputs/skill-bytecode-and-managed-formats.md. استخدمها لتحويل حاوية رمز البايت إلى تقرير رأس ، وإدراج معين لمهمة واحدة ، وجداول معلومات ترسم كل اسم ونوع ، والهيكل كما تم الحفاظ عليه أو فقدته. يتطلب أداة النموذج الخاصة بها كحكيم ، وتحقق النسخة قبل أي مفكّر ، وإعلان عن مكان كل حقيقة فقدت قد عاش.

تحقق من ذلك

إشغال التجربة والسلسلة التحديدية:

bash
cd phases/13-tools-and-protocols/43-bytecode-and-managed-formats
python3 code/main.py
npx tsx code/main.ts
python3 -m unittest discover -s code/tests -v

يجب أن تثبت التحقق:

  • تحتوي الرأس الأربعة على الكلمات السحرية 3495، 3531، 3571، و 3627، العلامات 3، والهاش 8 بايت، وملفات العلامات الزمنية تحتوي على العلامات 0، mtime 1791975565, والحجم 497
  • كل كلمة سحرية ل 3.11 و بعد ذلك يجلس في النطاق2900 + 50nالقاعدة تعطى إطلاقها
  • يعيد المُحاكم الأسماء، المستمرات، أجزاء رمزية، أسماء المتغيرات، و جدول الخطmarshal.loads()على الملف الذي كتب المترجم المدير
  • كل الملفات الأربعة تحتفظ بأسم الوحدات('score', 'bucket')لـgrade، أول سطر 10 ، و ledger.pyكاسم الملف
  • grade.co_codeهو 80، 62، 70، و 96 بايت في جميع النسخ الأربعة والقوائم التي تم التقاطها لديها 31، 26، 26، و 35 تعليمات
  • القائمة 3.11POP_JUMP_FORWARD_IF_FALSE3 ، 12 و 3 ، 13RETURN_CONSTو 3.14 لديهLOAD_SMALL_INT،LOAD_FAST_BORROWوNOT_TAKEN
  • 3.14 -C -Oيظهر القائمة 13 إدخال في الاحتفاظgrade، خمسة منهم بعدBINARY_OP، وترتيبات الإدراجاتCOMPARE_OP_INT
  • رأس بدون0d 0a، رأس محطم، وجسم ليس كود كائن رفع FormatError
  • قائمة التعليمات موجودة فقط للجهاز المكتب الذي كتبه المترجم الجاري وتطابق المقاطعdisالناتج
  • الملفات الفئة لديها 65 أو 69 أساسية، أحجام 1581, 1832, 1404 و 1581, وتعدد الجمع الثابت 82, 94, 79, و 82
  • مستمرة#13يقررMethod Ledger.grade:(I)Iو#47إلىString F
  • إنّ مُفكّر الـ JVM يوافق على javap -c -pعلى 108 من 108 تعليمات في كل أربع البناءات
  • tableswitchفي pc 4 هو 36 بايت مع 6 منخفضة، 10 منخفضة، 48 الافتراضي، والهدف 46, 44, 42, 40, 40
  • مستويات التحليل الثلاثة تغير عدد الصفات وتترك 50 بايت رمز من gradeمتطابقة
  • ifne،if_icmpgeوgotoالأهداف نسخية عن رمز الخيارات
  • سحرية خاطئة، تعقب البايتز، ورفع رمز الخيار غير محدد FormatError
  • ستة أقسام " واص " لديها تعويضات للحميل المفيدwasm-objdump -hالطوابع، والأسماء المُبنية يضيف nameقسم العمليات الإجتماعية في 293 إلى 425
  • النوع،env.logالإيرادات، الخمسة الصادرات، وقطاع البيانات في 1024 رمز التشريح كما هو مكتوب في ledger.wat
  • إنّ مُفكّر " ويزم " يوافق على ذلكwasm-objdump -dعلى 77 من 77 تعليمات في كل من البناء
  • gradeلديه 6 كتلة متجمعةbr_tableمع علامات4 4 4 4 4 4 3 2 1 0 0و 4 افتراضي في عمق 6 و 1 i32المحلية
  • أسماء الوظائف تأتي من الصادرات بدون قسم الأسماء والأسماء المحلية فقط معها
  • LEB128 e4 00هو 1007fهو -180 08هو 1024، وتعطي أنواع الكتل مثل wasm-objdump
  • إصدار 2 خاطئ، ورفع رمز الاختيار غير معروفFormatError
  • الجمع هو PE32 مع آلة 0x14c، عنوان CLI في RVA 0x2008, وقت التشغيل 2.5 ,ILONLY، و نقطة دخول0x06000005
  • نسخة البيانات المعدنية هي v4.0.30319، هناك خمسة تيار ، والجداول 14 لديها عدد الصفوف وحجم الصفوف تقارير الوساطة
  • قراءة .NET يوافقون على نظام.عكس.المعلومات المتعددة على 246 من 246 التحقق
  • Gradeلديه مُعيارscore, توقيعstatic int32(int32)، رأس سمين معMaxStack2 و 45 بايت رمز، و واحد int32محلية بدون اسم
  • (CIL)switchالأهدافbr.s،ldsfld،callوldstrالـ (أوبراند) يُحلّون عبر الجداول والكثائب
  • جدول CIL opcode يغطي كل رمز opcode في وقت التشغيل ويضيف فقط no.
  • تبلغ جدول الحفاظ على اسم المعلم في أربعة حاويات ولا في أي منها للرمز الأصلي، وتصنيف في ثلاثة
  • كل خط في التجربة يقرأ n من n
  • الرقم التفاعلي يضم نفس البيانات figure_data()تنتج

أساليب فشل الإنتاج

FailureWhat the weak tool reportsWhat the analysis must prove
Decompiler older than the interpreterUnsupported opcode, output marked incomplete, or a claim of obfuscationThe magic word, the release it names, and the tool's documented ceiling
pyc read with the wrong interpretermarshal.loads raises or returns garbageOur unmarshaller reads names, constants, and sizes from any 3.9 to 3.15 file, and instructions come from the matching dis
Specialised opcodes mistaken for the file's contentCOMPARE_OP_INT in a listingA pyc holds the unspecialised form, specialisation happens in memory after warm-up
Local names reported for a default javac buildvar1, var2 presented as source namesLocalVariableTable is present only with -g, the 50 code bytes are identical either way
Branch target off by the instruction lengthA JVM listing whose jumps land mid-instructionOffsets relative to the branch opcode, checked against javap
Switch padding skippedA tableswitch with a wrong default and shifted casesZero to three padding bytes to a 4-aligned pc, 36 bytes for five cases
Wasm names assumed stripped"no symbols"Exports name every exported function, locals need the name section, wasm-strip removes only that section
Three tools, three spellingsget_local versus local.get, a function at 0x8b versus 0x8eSame bytes, and the listing that the comparison was captured with
Table row size guessedEvery row after the first table misreadRow sizes from HeapSizes, row counts, and coded index widths, equal to the oracle's
Local names expected in a release assemblyV_0 presented as the source nameLocals have types in StandAloneSig and names only in a PDB that DebugType none did not write
Reader guesses an unknown opcode or type codeA plausible mnemonicFormatError with the offset, and the oracle comparison stops there
Oracle captured from another buildTests pass on stale textbuild_fixtures.sh names every tool version and writes versions.txt and sha256.txt

قاعدة العمليات

اقرأ الرأس أولاً وسمي المنتج الذي يشير إليه. اقرأ الحاوية مع قارئ يرفض ما لا يعرفه، و تحقق من قائمةها مع أداة النموذج الخاصة في نفس الملف. ثم قل، لكل اسم وتصفيف في إصدار المتحول، سواء كان الحاوية قد تخزنها أو أداة استنتجته.

المزيد من القراءة

This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.

Browse the complete course catalog or open this lesson on GitHub.