אילוצים

קובץ .dex הוא פורמט התעבורה של קוד באקס (bytecode) של Dalvik. יש אילוצים תחביריים וסמנטיים מסוימים שצריך לעמוד בהם כדי שקובץ יהיה קובץ .dex תקין, וסביבת זמן ריצה צריכה לתמוך רק בקובצי ‎ .dex תקינים.

אילוצים כלליים על תקינות קובצי ‎ .dex

אילוצים כלליים של תקינות קשורים למבנה הרחב יותר של קובץ .dex, כפי שמתואר בפירוט בפורמט .dex.

מזהה תיאור
G1 המספר magic בקובץ .dex צריך להיות dex\n035\0 בגרסה 35, או מספר דומה בגרסאות מאוחרות יותר.
G2 סיכום הביקורת חייב להיות סיכום ביקורת Adler-32 של כל תוכן הקובץ, מלבד השדות magic ו-checksum.
G3 החתימה חייבת להיות גיבוב SHA-1 של כל תוכן הקובץ, מלבד magic, ‏ checksum ו-signature.
G4

השדה file_size חייב להתאים לגודל הקובץ בפועל, בבייט. (גרסה 40 ואילך)

השדה file_size חייב להפנות לכותרת הבאה בקונטיינר, או לסוף הקובץ הפיזי (הקונטיינר). אם הוא מפנה לכותרת הבאה, גודל הקובץ חייב להיות מיושר ל-4 בייטים. הסכום של כל שדות file_size חייב להיות שווה ל-container_size. (גרסה 41 ואילך)

G5

הערך של header_size חייב להיות: 0x70 (v40 או גרסה קודמת)

הערך של header_size חייב להיות: 0x78 (v41 ואילך)

G6 הערך של endian_tag חייב להיות: ENDIAN_CONSTANT או REVERSE_ENDIAN_CONSTANT
G7

בכל אחד מהקטעים link,‏ string_ids,‏ type_ids,‏ proto_ids,‏ field_ids,‏ method_ids,‏ class_defs ו-data, השדות offset ו-size חייבים להיות אפס או לא אפס. במקרה השני, ההיסט חייב להיות מיושר לארבעה בייטים.

השדות offset ו-size חייבים להיות בתוך המאגר, ולהפנות לנתונים שנמצאים אחרי הכותרת שמגדירה אותם. (גרסה 41 ואילך)

G8 כל שדות ה-offset בכותרת, מלבד map_off, חייבים להיות מותאמים לארבעה בייטים.
G9 השדה map_off חייב להיות אפס או להפנות למקטע הנתונים. במקרה השני, המקטע data חייב להתקיים.
G10 אסור שחלקים link, ‏ string_ids,‏ type_ids, ‏ proto_ids, ‏ field_ids,‏ method_ids, ‏ class_defs ו-data יחולו זה על זה או על הכותרת.
G11 אם המפה קיימת, לכל רשומה במפה צריך להיות סוג תקין. כל סוג יכול להופיע פעם אחת לכל היותר.
G12 אם המפה קיימת, לכל רשומה במפה צריכים להיות גודל וזזוג (offset) שאינם אפס. ההיסט חייב להצביע על הקטע המתאים בקובץ (כלומר, string_id_item חייב להצביע על הקטע string_ids) והגודל המפורש או המשתמע של הפריט חייב להתאים לתוכן ולגודל בפועל של הקטע.
G13 אם קיימת מפה, היסט הרשומה n+1 במפה חייב להיות גדול מ-n plus than size of map entry n או שווה לו. המשמעות היא שהרשאות לא חופפות והן מסודרות מערכים נמוכים לערכים גבוהים.
G14 לסוגים הבאים של רשומות צריך להיות אופלס שמותאם לארבע בייטים: string_id_item,‏ type_id_item, ‏ proto_id_item,‏ field_id_item,‏ method_id_item, ‏ class_def_item,‏ type_list, ‏ code_item,‏ annotations_directory_item.
G15

לכל string_id_item, השדה string_data_off חייב להכיל הפניה תקפה למקטע data. (גרסה 40 ואילך)

לכל string_id_item, השדה string_data_off חייב להיות אופסט בתוך המאגר, אחרי כל כותרת שמשתמשת בו באופן טרנזיטיבי. (גרסה 41 ואילך)

בשדה data של הערך המפנה string_data_item, צריכה להופיע מחרוזת MUTF-8 תקינה, והשדה utf16_size צריך להתאים לאורך המחרוזת לאחר פענוח.

G16 לכל type_id_item, השדה descriptor_idx חייב להכיל הפניה תקפה לרשימה string_ids. המחרוזת שצוינה צריכה להיות מתארת סוג תקינה.
G17 לכל proto_id_item, השדה shorty_idx חייב להכיל הפניה תקפה לרשימה string_ids. המחרוזת שצוינה צריכה להיות מתארת של קיצור דרך תקינה. כמו כן, השדה return_type_idx חייב להיות אינדקס חוקי בקטע type_ids, והשדה parameters_off חייב להיות אפס או שינוי אופסט חוקי שמפנה לקטע data. אם הערך שונה מאפס, רשימת הפרמטרים לא יכולה לכלול רשומות ריקות.
G18 לכל field_id_item, השדות class_idx ו-type_idx חייבים להיות אינדקסים תקפים ברשימה type_ids. הערך שמתייחס אליו class_idx חייב להיות הפניה מסוג שאינו מערך. בנוסף, השדה name_idx חייב להיות הפניה תקינה לקטע string_ids, ותוכן הרשומה שאליו מופנית ההפניה חייב לעמוד במפרט MemberName.
G19 לכל method_id_item, השדה class_idx חייב להיות אינדקס חוקי למדור type_ids, והרשומה שאליה מופנית ההפניה חייבת להיות מסוג הפניה שאינה מערך. השדה proto_id חייב להיות הפניה תקינה לרשימה proto_ids. השדה name_idx חייב להיות הפניה תקינה לקטע string_ids, ותוכן הרשומה שאליו מופנית ההפניה חייב לעמוד במפרט MemberName.
G20 לכל field_id_item, השדה class_idx חייב להיות אינדקס תקין ברשימה type_ids. הרשומה שצוינה צריכה להיות מסוג הפניה שאינה מערך.

אילוצים של קוד בייט סטטי

אילוצים סטטיים הם אילוצים על רכיבים ספציפיים של קוד ה-bytecode. בדרך כלל אפשר לבדוק אותם בלי להשתמש בשיטות של בקרה או ניתוח תעבורת נתונים.

מזהה תיאור
A1 מערך insns לא יכול להיות ריק.
A2 האינדקס של קוד הפקודה הראשון במערך insns חייב להיות אפס.
A3 מערך insns חייב להכיל רק קוד opcode תקף של Dalvik.
A4 האינדקס של ההוראה n+1 חייב להיות שווה לאינדקס של ההוראה n בתוספת האורך של ההוראה n, תוך התחשבות באפשרויות של אופרנדים.
A5 ההוראה האחרונה במערך insns חייבת להסתיים במדד insns_size-1.
A6 כל היעדים של goto ו-if-<kind> חייבים להיות opcodes באותו method.
A7 כל היעדים של הוראה packed-switch חייבים להיות אופרקודים באותו method. הגודל והרשימה של היעדים חייבים להיות עקביים.
A8 כל היעדים של הוראה sparse-switch חייבים להיות אופרקודים באותו method. הטבלה התואמת חייבת להיות עקבית וממוינים מקטן לגדול.
A9 המשתנה B של ההוראות const-string ו-const-string/jumbo חייב להיות אינדקס תקין במאגר הקבועים של המחרוזות.
A10 המשתנה C של ההוראות iget<kind> ו-iput<kind> חייב להיות אינדקס תקין למאגר הקבועים של השדה. הרשומה שצוינה צריכה לייצג שדה של מכונה.
A11 המשתנה C של ההוראות sget<kind> ו-sput<kind> חייב להיות אינדקס תקין למאגר הקבועים של השדה. הרשומה שצוינה צריכה לייצג שדה סטטי.
A12 המשתנה C של ההוראות invoke-virtual,‏ invoke-super, ‏ invoke-direct ו-invoke-static חייב להיות אינדקס תקין במאגר הקבועים של השיטה.
A13 המשתנה B של ההוראות invoke-virtual/range,‏ invoke-super/range,‏ invoke-direct/range ו-invoke-static/range חייב להיות אינדקס תקין במאגר הקבועים של השיטה.
A14 אפשר להפעיל שיטה ששמה מתחיל ב-'<' רק באופן סמלי על ידי המכונה הווירטואלית, ולא על ידי קוד שמקורו בקובץ .dex. החריג היחיד הוא ה-initializer של המופע, שאפשר להפעיל באמצעות invoke-direct.
A15 המשתנה C של ההוראה invoke-interface חייב להיות אינדקס תקין במאגר הקבועים של השיטה. המשתנה method_id שמצוין בהפניה חייב להיות שייך לממשק (ולא לכיתה).
A16 המשתנה B של ההוראה invoke-interface/range חייב להיות אינדקס תקין במאגר הקבועים של השיטה. המשתנה method_id שמצוין בהפניה חייב להיות שייך לממשק (ולא לכיתה).
A17 המשתנה B של ההוראות const-class,‏ check-cast,‏ new-instance ו-filled-new-array/range חייב להיות אינדקס תקף במאגר הקבועים של הסוגים.
A18 המשתנה C של ההוראות instance-of,‏ new-array ו-filled-new-array חייב להיות אינדקס תקף במאגר הקבועים של הסוגים.
A19 המימדים של מערך שנוצר באמצעות הוראה new-array חייבים להיות קטנים מ-256.
A20 אסור להפנות את ההוראה new לממשקי, למחלקות מערך או למחלקות מופשטים.
A21 הסוג שאליו מפנה ההוראה new-array חייב להיות סוג חוקי שאינו סוג הפניה.
A22 כל הרשומות שמתייחסות להוראה ברוחב יחיד (לא זוג) חייבות להיות תקפות לשיטה הנוכחית. כלומר, האינדקסים שלהם חייבים להיות לא שליליים וקטנים מ-registers_size.
A23 כל הרשומות שמתייחסות להוראה בפורמט של רוחב כפול (זוג) חייבות להיות תקפות לשיטה הנוכחית. כלומר, האינדקסים שלהם חייבים להיות לא שליליים וקטנים מ-registers_size-1.
A24 המשתנה method_id של ההוראות invoke-virtual ו-invoke-direct חייב להיות שייך לכיתה (ולא לממשק). בקובצי Dex בגרסה 037 ואילך, התנאי הזה חייב להתקיים גם לגבי ההוראות invoke-super ו-invoke-static.
A25 המשתנה method_id של ההוראות invoke-virtual/range ו-invoke-direct/range חייב להיות שייך לכיתה (ולא לממשק). בקובצי Dex בגרסה 037 ואילך, התנאי הזה חייב להתקיים גם לגבי ההוראות invoke-super/range ו-invoke-static/range.

מגבלות על קוד בייט מבני

אילוצים מבניים הם אילוצים על היחסים בין כמה רכיבים של הקוד. בדרך כלל אי אפשר לבדוק אותם בלי להשתמש בשיטות של בקרה או ניתוח תעבורת נתונים.

מזהה תיאור
B1 מספר הארגומנטים והסוגים שלהם (רישומים וערכים מיידיים) חייבים תמיד להתאים להוראה.
B2 אסור לפרק זוגות של רשומות.
B3 צריך להקצות רישום (או זוג) לפני שאפשר לקרוא אותו.
B4 הוראה invoke-direct חייבת להפעיל מאתחלת של מופע או שיטה רק בכיתה הנוכחית או באחת מהסופר-כיתות שלה.
B5 צריך להפעיל את ה-initializer של המכונה רק במכונה שלא בוצע לה אתחול.
B6 אפשר להפעיל שיטות של מופעים רק במופעים שכבר הופעלו, וגישה לשדות של מופעים אפשרית רק במופעים שכבר הופעלו.
B7 אסור להשתמש ברשומה שמכילה את התוצאה של הוראה new-instance אם אותה הוראה new-instance מופעלת שוב לפני שמפעילים את המכונה.
B8 מפעיל המכונה של המופע חייב לקרוא למפעיל מכונה אחר של מופע (מאותה כיתה או מאותה סופר-כיתה) לפני שאפשר לגשת למאפיינים של המופע. חריגים הם שדות של מופעים שלא עוברים בירושה, שאפשר להקצות לפני שמפעילים מערך נתונים אחר, והכיתה Object באופן כללי.
B9 כל הארגומנטים בפועל של השיטה חייבים להיות תואמים להקצאה לארגומנטים הפורמליים המתאימים שלהם.
בּֽי 10 בכל קריאה ל-method של מופע, המופע בפועל חייב להיות תואם להקצאה של הכיתה או הממשק שצוינו בהוראה.
B11 ההוראה return<kind> חייבת להתאים לסוג ההחזרה של השיטה.
B12 כשנכנסים למאפיינים מוגנים של סופר-קלאס, הסוג בפועל של המופע שאליו נכנסים חייב להיות הכיתה הנוכחית או אחת מהסופר-כיתות שלה.
B13 סוג הערך ששמור בשדה סטטי חייב להיות תואם להקצאה לסוג השדה או שניתן להמיר אותו לסוג השדה.
B14 סוג הערך ששמור בשדה חייב להיות תואם להקצאה לסוג השדה או שניתן להמיר אותו לסוג השדה.
B15 הסוג של כל ערך שנשמר במערך חייב להיות תואם למתן הערך לסוג הרכיב של המערך.
B16 המשתנה A של הוראה throw חייב להיות תואם להקצאה של java.lang.Throwable.
B17 ההוראה האחרונה שאפשר להגיע אליה בשיטה חייבת להיות goto או הסתעפות לאחור, return או throw. אסור להשאיר את מערך insns בתחתית.
B18 אי אפשר לקרוא את החלק שלא הוקצה של זוג רישום לשעבר (הוא נחשב לא חוקי) עד שהוא יוקצה מחדש באמצעות הוראה אחרת.
B19 לפני הוראת move-result<kind> חייבת להופיע הוראת invoke-<kind> (באוסף insns). היוצא מן הכלל היחיד הוא ההוראה move-result-object, שיכולה גם להיות מקדימה לה הוראה filled-new-array.
B20 לפני הוראה move-result<kind> חייבת להופיע (בזרימת הבקרה בפועל) הוראה return-<kind> תואמת (אסור לקפוץ אליה). היוצא מן הכלל היחיד הוא ההוראה move-result-object, שיכולה גם להיות מקדימה לה הוראה filled-new-array.
B21 הוראה move-exception חייבת להופיע רק כהוראה הראשונה בטיפול בחריגה.
B22 אסור שזרימת הבקרה תגיע לפקודות הפסאודו packed-switch-data,‏ sparse-switch-data ו-fill-array-data.