Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

โพรบ

<probe_rule> / <predicate> / { <actions> }

เราใช้คำว่า probe (โพรบ) เพื่ออ้างถึงสามส่วนนี้ ได้แก่ probe_rule, predicate และ actions

เมื่อทำการเขียนไบต์โค้ดใหม่ Whamm จะทำงานดังนี้:

  1. ท่องไปตามโมดูล Wasm ของแอปพลิเคชันเพื่อค้นหาตำแหน่งที่สนใจตามที่ระบุไว้ใน probe_rule ของแต่ละโพรบ
  2. ตรวจสอบว่า predicate ประเมินเป็น false แบบสแตติกหรือไม่
    • ถ้าประเมินเป็น false ก็จะเดินหน้าต่อ โดยไม่ฉีด actions ของโพรบ
    • ถ้าไม่ประเมินเป็น false ก็จะฉีด actions ของโพรบที่ตำแหน่งนั้น พร้อมกับ predicate ที่ถูกพับค่าแล้ว
      • ถ้า predicate ประเมินเป็น true แบบสแตติก ก็จะฉีด actions เข้าไปในโปรแกรมโดยไม่มีเงื่อนไข
      • ถ้า predicate ไม่พับเป็นค่า boolean ธรรมดา ก็จะฉีด actions ที่มีเงื่อนไข ณ ตำแหน่งนี้ จากนั้น predicate จะถูกประเมินแบบพลวัตเมื่อแอปพลิเคชันรัน เพื่อให้ actions ของโพรบทำงานตามเงื่อนไข

ตัวช่วย info ใน CLI

whamm info --help

คำสั่ง info ที่ CLI ให้มาเป็นแหล่งข้อมูลชั้นเยี่ยมสำหรับดูว่าอะไรใช้เป็นกฎการแมตช์ของโพรบได้บ้าง คำสั่งนี้ให้เอกสารที่อธิบายส่วนประกอบของกฎการแมตช์ ตลอดจนตัวแปรและฟังก์ชันที่ผูกไว้ซึ่งอยู่ในสโคป ซึ่งช่วยให้ผู้ใช้เรียนรู้วิธีสร้าง instrumentation ของตนได้เป็นอย่างดี

กฎการแมตช์ของโพรบ

provider:package:event:mode

probe_rule เป็นวิธีแสดง “ตำแหน่ง” ที่คุณต้องการทำ instrumentation ในโปรแกรม มันเป็นลำดับชั้นตาม provider, package, event และ mode

ส่วนคำอธิบาย
providerชื่อของ provider ที่รองรับความสามารถ instrumentation ที่ใช้ในโพรบนี้
packageชื่อของ package ภายใน provider ที่ระบุ ซึ่งรองรับความสามารถ instrumentation ที่ใช้ในโพรบนี้
eventชื่อของ event ที่สัมพันธ์กับตำแหน่งที่จะแทรกโพรบนี้ในโปรแกรมที่ทำ instrumentation
modeชื่อของ mode ที่ควรใช้เมื่อปล่อย actions ของโพรบ ณ ตำแหน่งของ event เช่น before, after และ alt

แต่ละส่วนของ probe_rule จะเพิ่มความจำเพาะขึ้นเรื่อยๆ จนกระทั่งถึง mode ของโพรบ ลองพิจารณากฎการแมตช์ตัวอย่าง: wasm:opcode:br_if:before กฎนี้ตีความได้ว่า “แทรกโพรบนี้ก่อนแต่ละ ออปโคด br_if ของ Wasm ในโปรแกรมของฉัน”

อ่านเอกสารอีเวนต์ที่ทำ instrumentation ได้ของเราเพื่อดูสิ่งที่รองรับในปัจจุบันและเป้าหมายในอนาคต

เพรดิเคต

/ <predicate> /

predicate เป็นวิธีแสดง “เงื่อนไข” ที่คุณต้องการให้ประเมินเป็น true เพื่อให้ actions ของโพรบถูกทำ มันช่วยจำกัดกฎการแมตช์ให้แคบลงอีกชั้น ส่วนนี้ของโพรบเป็นทางเลือก ถ้าโพรบใดไม่มี predicate actions จะถูกทำเสมอเมื่อถึงตำแหน่งของโพรบระหว่างการทำงานของโปรแกรม

การพับค่าคงที่ของข้อมูลสแตติก

โพรบสามารถมีเพรดิเคตบนข้อมูลทั้งสแตติกและพลวัตได้ เพื่อรองรับสิ่งนี้ เมื่อกำหนดเป้าหมายเป็นการเขียนไบต์โค้ดใหม่ คอมไพเลอร์ whamm จะทำการแพร่ค่าคงที่สำหรับข้อมูลที่นิยามแบบสแตติก หมายความว่า เนื่องจากข้อมูลสแตติกรู้ได้ตั้งแต่ตอนคอมไพล์ไทม์ ค่าของตัวแปรเหล่านั้นจะถูกแทนที่ และนิพจน์สามารถประเมินบางส่วนได้

ตัวอย่างเช่น ลองพิจารณาโพรบต่อไปนี้: wasm:opcode:br_if:before / pc == 25 && arg0 == 1 / {..}

อ่านได้ว่า แนบโพรบที่ออปโคด wasm br_if แต่รันตรรกะนี้เฉพาะเมื่อ pc เป็น 25 และ arg0 ประเมินเป็น 1 ขณะที่เราท่องไปตามแอปพลิเคชัน เรารู้แบบสแตติกว่าเรากำลังอยู่ที่ออฟเซต pc เท่ากับ 25 ภายในฟังก์ชัน แต่เราไม่รู้ค่าของ arg0 จนกว่าโค้ดจะรันจริง! นี่คือจุดที่การประเมินบางส่วนเข้ามามีบทบาท

สมมติว่าเราอยู่ที่ pc 0 ภายในฟังก์ชันหนึ่ง การแพร่ค่าคงที่และการประเมินบางส่วนจะมีลักษณะดังนี้:

0 == 25 && arg0 == 1
false && arg0 == 1
false

เพรดิเคตประเมินเป็น false แบบสแตติก! นั่นหมายความว่าเราไม่ควรแนบโพรบที่ตำแหน่งนี้ เพราะมันไม่แมตช์!

สมมติว่าเราอยู่ที่ pc 25 ภายในฟังก์ชันหนึ่ง:

25 == 25 && arg0 == 1
true && arg0 == 1
arg0 == 1

อืม … เรายังมีส่วนหนึ่งของเพรดิเคตเหลืออยู่! ควรทำอย่างไรดี … เรายังจำเป็นต้องมีเพรดิเคตบนส่วนนี้ของนิพจน์ เพียงแต่ต้องฉีดนิพจน์ที่ประเมินบางส่วนแล้วนี้ออกไปรันตอนรันไทม์! ดังนั้น เราจะฉีดเนื้อโพรบโดยห่อด้วยเงื่อนไขนี้!

โปรดทราบว่าสิ่งนี้มีลักษณะแตกต่างออกไปเล็กน้อยสำหรับเป้าหมาย wei เพราะ Whamm ต้องปรับแต่งเพรดิเคตเป็นอย่างอื่นตรงจุดนั้น ซึ่งช่วยให้เอนจินรันส่วนที่ถูกต้องของเพรดิเคตในเวลาที่ถูกต้อง (match time กับรันไทม์)

Actions

{ <actions> }

actions คือคำสั่งที่ถูกทำ ณ ตำแหน่งของ probe_rule หาก predicate ประเมินเป็น true

ลำดับการฉีดโพรบ

เมื่อมีโพรบหลายตัวแมตช์ตำแหน่งไบต์โค้ดเดียวกัน whamm รับประกันลำดับการฉีดภายใต้กฎสองข้อ:

กฎข้อ 1: หมวดหมู่โพรบเดียวกัน — ลำดับในสคริปต์ถูกคงไว้

โพรบสองตัวที่อยู่ในหมวดหมู่การฉีดเดียวกัน (เช่น เป็น opcode:call:before ทั้งคู่ หรือเป็น func:entry ทั้งคู่) จะถูกฉีดตามลำดับที่ปรากฏในสคริปต์เสมอ

// order0.mm — func:entry fires first, then the second func:entry
wasm:func:entry { /* A */ }
wasm:func:entry { /* B */ }
// at any function entry: A runs, then B runs

การรับประกันนี้ยังใช้ได้กับสคริปต์หลายไฟล์ที่ส่งให้คอมไพเลอร์ด้วย: โพรบจากสคริปต์แรกจะถูกฉีดก่อนโพรบจากสคริปต์ที่สอง

กฎข้อ 2: หมวดหมู่โพรบต่างกัน — ลำดับถูกกำหนดโดยเป้าหมายการฉีด

เมื่อโพรบสองตัวอยู่ต่างหมวดหมู่การฉีดกัน (เช่น wasm:opcode:call:before กับ wasm:func:entry) ลำดับสัมพัทธ์ ณ ตำแหน่งที่ใช้ร่วมกันไม่ถูกควบคุมด้วยลำดับในสคริปต์

เป้าหมายการเขียนไบต์โค้ดใหม่ (wirm) ใช้โมเดลการฉีดสองรอบ:

  • รอบที่ 1 (ปกติ): โพรบ before, after และ alt ถูกฉีดระหว่างการท่องไบต์โค้ด
  • รอบที่ 2 (โหมดพิเศษ): โพรบเชิงโครงสร้างอย่าง func:entry, func:exit, block:entry, block:exit และอื่นๆ ที่คล้ายกัน ถูกแก้ไขให้ชัดเจนและฉีดตอน encode

เนื่องจากสองรอบนี้เป็นอิสระต่อกัน โพรบ before จึงถูกฉีดก่อนโพรบ func:entry ณ ตำแหน่งไบต์โค้ดเดียวกัน (คำสั่งแรกของฟังก์ชัน) เสมอ ไม่ว่าโพรบใดจะปรากฏก่อนในสคริปต์

หากคุณต้องการลำดับที่เฉพาะเจาะจงระหว่างโพรบต่างหมวดหมู่ ให้ใส่ตรรกะทั้งหมดไว้ในโพรบเดียวที่อีเวนต์จำเพาะกว่า (เช่น opcode:call:before แทนที่จะผสม func:entry กับ opcode:call:before ที่ตำแหน่งเดียวกัน)