Quan hệ chuyển tiếp: Để biểu diễn ngữ nghĩa của chương trình bằng cách người ta xây dựng các quan hệ chuyển tiếp (transition relation), còn được gọi là ngữ nghĩa chuyển tiếp (transition semantics) là một tập tích Σ × Σ. Trong
42
đó Σ được gọi là tập trạng thái của chương trình. Với , ′ ∈ Σ ta có → ′ ∈ Σ × Σ là một quan hệ chuyển tiếp từ trạng thái sang trạng thái ’ [3][12][5].
Ví dụ: 1. a = 0; 2. while(a < 1000){ 3. a = a + 1; 4. } 5. return;
Khi đó các quan hệ dịch chuyển được mô tả là một chuỗi như sau:
〈1, ⇒ ⍵〉 → 〈2, ⇒ 0〉 → 〈3, ⇒ 0〉 → 〈4, ⇒ 1〉 → ⋯ → 〈5, ⇒ 1000〉.
Hình 2.22: Biểu diễn quan hệ chuyển tiếp ngữ nghĩa chương trình
Hệ dịch chuyển (transition systems) là một bộ = 〈 , , 〉 trong đó
⊆ là tập các trạng thái khởi đầu và ⊆ × là một quan hệ chuyển tiếp giữa một trạng thái và các trạng thái kế tiếp có thể của nó [3][12][5].
Biểu diễn của ví dụ trên: 〈ℤ, {0}, {〈 , ′〉| < 1000 ∧ ′= + 1}〉.
43 2.7.2. Ngữ nghĩa vết (Trace semantics)
Một thực thi của chương trình sẽ cho ra một sự tương tác cụ thể được đưa ra với môi trường của nó là một chuỗi của các trạng thái, được quan sát trong khoảng thời gian rời rạc được gọi là phân đoạn vết thực thi hữu hạn
, , . . . , bắt đầu từ trạng thái ∈ và sau đó dịch chuyển qua các trạng thái chuyển tiếp , < , tới một trạng thái kế tiếp là bằng cách thực hiện một bước đơn trong chương trình thỏa mãn điều kiện 〈 , 〉 ∈ .
Tập hợp tất cả các phân đoạn vết thực thi hữu hạn như vậy được gọi là ngữ nghĩa vết (Trace semantics) của hệ thống dịch chuyển, ký hiệu là: ∑ ∗⃗ , ngữ nghĩa vết của chương trình được biểu diễn trong hình 2.24 [3][12][5].
Hình 2.24: Biểu diễn ngữ nghĩa vết thực thi
Vì tập là tập tất cả các phân đoạn vết có độ dài 0 là tập rỗng, nên không có phân đoạn vết nào có độ dài bằng 0. Tập tất cả các phân đoạn vết có độ dài là 1 thì nó chính là tập các trạng thái của chương trình: . Vì vậy, tập các phân đoạn vết có độ dài 1 được biểu diễn: = { | ∈ }. Tương tự như vậy, một phân đoạn vết có độ dài + 1 được tạo ra bằng phép ghép (phép hội) chuỗi trạng thái của chương trình: ′ từ phân đoạn vết có độ dài với một phân đoạn vết ′ có độ dài 1, thỏa mãn điều kiện 〈 , ′〉 ∈ là một trạng thái chuyển tiếp có thể của chương trình.
44
Tuy nhiên, nếu là tập các phân đoạn vết có độ dài thì tập các phân đoạn vết có độ dài + 1 là: = { ′| ∈ ∧ 〈 , ′〉 ∈ }. Do đó, ngữ nghĩa vết của là tập ∗⃗ = ⋃ (hợp của tất cả các phân đoạn vết có độ dài hữu hạn). [3][12][5]
2.7.3. Biểu diễn ngữ nghĩa vết dưới dạng điểm cố định
Ta nhận thấy rằng: ∪ = ℱ∗⃗ ( ) với: ℱ∗⃗ ( ) = { | ∈ } ∪ { ′| ∈ ∧ 〈 , ′〉 ∈ ⇒ ∗⃗ là một điểm cố định (fixpoint) của ℱ∗⃗ vì
ℱ∗⃗( ∗⃗) = ∗⃗.
Chứng minh: ℱ∗⃗( ∗⃗) = ℱ∗⃗(⋃ ) (theo định nghĩa ∗⃗)
= { | ∈ } ∪ { ′ ∈ (⋃ ) ∧ 〈 , ′〉 ∈ } (theo định nghĩa ℱ∗⃗)
= { | ∈ } ∪ ⋃ { ′ ∈ ∧ 〈 , ′〉 ∈ } (theo lý thuyết tập hợp)
= ∪ ⋃ = ⋃ ′
′ = ⋃ (theo định nghĩa và , và
bằng cách cho ′ = + 1 và từ = ∅)
Bây giờ ta giả sử rằng ℱ∗⃗ ( ) = là một điểm cố định khác của ℱ∗⃗. Ta chứng minh bằng qui nạp ∀ ≥ 0: ⊆ . Rõ ràng: = ∅ ⊆ .
= { | ∈ } ⊆ ℱ∗⃗( ) = . Công thức qui nạp ⊆ đúng với ≥ 0. Ta chứng minh công thức ⊆ đúng với + 1.
Ta có ∈ ⇒ ∈ do đó { ′| ∈ ∧ 〈 , ′〉 ∈ } ⊆
{ ′| ∈ ∧ 〈 , ′〉 ∈ } khi đó ⊆ ℱ∗⃗ ( ) ⊆ ℱ∗⃗ ( ) =
45
Với ∀ ≥ 0: ⊆ ⇒ ∗⃗ là điểm cố định nhỏ nhất (least fixpoint) của ℱ∗⃗, ký hiệu là: ∗⃗ = ∅⊆ℱ∗⃗ = ⋃ ℱ∗⃗ (∅) khi đó ( ) = và
( ) = ( ( )) là hàm lặp của hàm [9][5].
2.7.4. Bao đóng phản xạ bắc cầu (RTC - reflexive transitive closure) là trừu tượng hóa của ngữ nghĩa vết trừu tượng hóa của ngữ nghĩa vết
Sử dụng các phân đoạn vết thực thi là rất chính xác để thể hiện thuộc tính của chương trình nhưng trong nhiều trường hợp các bước tính toán trung gian là không cần thiết. Xem xét trạng thái ban đầu và các trạng thái kết thúc là một trừu tượng hóa: ∗( ) = { ⃗( )| ∈ } ℎ ⃗( . . . ) = 〈 , 〉
Quan sát thấy ∗( ∗⃗) là một bao đóng phản xạ bắc cầu ∗của quan hệ chuyển tiếp , nghĩa là với mỗi cặp 〈 , ′〉 có một đường đi hữu hạn trong đồ thị = 〈 , , 〉 đi từ đỉnh tới đỉnh ′ thông qua các cung của t: 〈 , 〉 ∈ ∗ nếu và chỉ nếu ∃ , . . . , ∈ : = ∧ . . .∧ 〈 , 〉 ∈ ∧ . . .∧ =
Nếu là một tập hợp các cặp trạng thái ban đầu và kết thúc, nó mô tả một tập hợp các phân đoạn vết khi đó các trạng thái trung gian là không cần biết đến. Ta định nghĩa ∗( ) = { | ⃗( ) ∈ } = { . . . |〈 , 〉 ∈ }
Vì thế, nếu là một tập hợp phân đoạn vết thì nó chính là xấp xỉ như ở trên cho bởi ∗( ) với ý nghĩa là ⊆ ∗( ∗( )) [5].
2.7.5. Thỏa mãn kết nối Galois
Cho tập bất kì là các phân đoạn vết và là tập các cặp trạng thái, chúng ta có:
∗( ) ⊆ ⟺ { ⃗( )| ∈ } ⊆ (theo định nghĩa ∗)
⟺ ∀ ∈ : ⃗( ) ∈ ⟺ ⊆ { | ⃗( ) ∈ } (theo định nghĩa ⊆)
⟺ ⊆ ∗( ) (theo định nghĩa ∗)
Do đó ∗( ) ⊆ nếu và chỉ nếu ⊆ ∗( ) (đó là thuộc tính đặc trưng của kết nối Galois). Kết nối Galois bảo toàn phép hợp trong đó:
46
Nội dung trên đã chỉ ra rằng bao đóng phản xạ bắc cầu là một trừu tượng hóa của ngữ nghĩa vết và nó thỏa mãn kết nối Galois.
2.7.6. Biểu diễn ngữ nghĩa RTC dưới dạng điểm cố định
Khi ngữ nghĩa cụ thể (ngữ nghĩa vết) có thể được biểu diễn dưới dạng điểm cố định và ngữ nghĩa trừu tượng (ngữ nghĩa bao đóng phản xạ bắc cầu) là một trừu tượng hóa của ngữ nghĩa cụ thể bằng một kết nối Galois, chúng ta cũng có thể biểu diễn ngữ nghĩa trừu tượng này dưới dạng điểm cố định. Đây là một nguyên tắc tổng quát trong kỹ thuật giải thích trừu tượng [5].
Ta có ∅ ⊆ ∗(∅) do ∗(∅) ⊆ ∅, chứng tỏ rằng ∗(∅) = ∅ do tính phản đối xứng. Với mọi tập các phân đoạn vết, chúng ta có tính chất chuyển đổi như sau: ∗ ℱ∗⃗( ) = ∗ { | ∈ } ∪ { ′ ∈ ∧ 〈 , ′〉 ∈ } (theo định nghĩa ℱ∗⃗) = { ⃗( )| ∈ } ∪ { ⃗( ′)| ∈ ∧ 〈 , ′〉 ∈ } (theo định nghĩa ∗) = {〈 , 〉| ∈ } ∪ {〈 0, ′〉|∃ : ∈ ∧ 〈 , ′〉 ∈ } (theo định nghĩa ⃗) = ∪ {〈 , ′〉|∃ : 〈 , 〉 ∈ ∗( ) ∧ 〈 , ′〉 ∈ (theo định nghĩa = {〈 , 〉| ∈ } và ∗)
= ∪ ∗( ) ∘ = ℱ∗( ∗( ))(theo định nghĩa phép hợp ∘ của quan hệ và bằng định nghĩa ℱ∗( ) = ∪ Y ∘ t )
Bằng phép lặp, mà hàm lặp ℱ∗⃗ (∅) của ℱ∗⃗( ) và hàm lặp ℱ∗ (∅) của
ℱ∗ là có quan hệ với nhau bằng hàm ∗ [5].
Về cơ bản ta có ∗(ℱ∗⃗ (∅) = ∅ = ℱ∗ (∅).
Cho các bước qui nạp, nếu ∗ ℱ∗⃗ (∅) = ℱ∗ (∅) thì ∗ ℱ∗⃗ (∅) = ∗ ℱ∗⃗ ℱ∗⃗ (∅) = ℱ∗ ∗ ℱ∗⃗ (∅) = ℱ∗ ℱ∗ (∅) = = ℱ∗ (∅).
Tiếp theo đó, ∗ ∗⃗ = ∗ ∅⊆ℱ∗⃗( ) = ∗ ⋃ ℱ∗⃗ (∅) = ⋃ ∗ ℱ∗⃗ (∅) = ⋃ ∗ ℱ∗ (∅) = ∅⊆ℱ∗.
47
Điều này có thể dễ dàng được tổng quát hóa về mặt lý thuyết và được biết đến như là lý thuyết chuyển đổi điểm cố định (fixpoint transfer) [5].
Quan sát thấy rằng nếu là hữu hạn thì định nghĩa điểm cố định cung cấp một thuật toán lặp cho việc tính toán bao đóng phản xạ bắc cầu của một quan hệ dạng = ∅, . . , = ℱ∗ , .., cho đến khi = = ∅⊆ℱ∗ = ∗.
2.7.7. Ngữ nghĩa tới được là trừu tượng hoá của ngữ nghĩa RTC
Ngữ nghĩa tới được của hệ dịch chuyển = 〈 , , 〉 là một tập
{ ′|∃ ∈ : 〈 , ′〉 ∈ ∗} các trạng thái mà là tới được từ các trạng thái khởi đầu . Đây là một trừu tượng •( ∗) của ngữ nghĩa bao đóng phản xạ bắc cầu ∗ bởi định nghĩa ảnh phải (Right-image) [ ] = { ′|∃ ∈ : 〈 , ′〉 ∈
} của tập với quan hệ và •( ) = [ ] = { ′|∃ ∈ : 〈 , ′〉 ∈ }. Để cho •( ) = {〈 , ′〉| ∈ ⟹ ′ ∈ }. Chúng ta có kết nối Galois: •( ) ⊆ ⟺ { ′|∃ ∈ : 〈 , ′〉 ∈ } ⊆ (theo định nghĩa •)
⟺ ∀ ′: ∀ ∈ : 〈 , ′〉 ∈ ⟹ ′ ∈ (theo định nghĩa quan hệ bao hàm ⊆)
⟺ ∀〈 , ′〉 ∈ : ∈ ⟹ ′ ∈ (theo định nghĩa phép kéo theo ⟹)
⟺ ⊆ {〈 , ′〉 ∈ ⇒ ′ ∈ } ⟺ ⊆ •( ) (theo định nghĩa ⊆, •) [5] 2.7.8. Biểu diễn ngữ nghĩa tới được dưới dạng điểm cố định
Để thiết lập tính chất chuyển đổi, chúng ta chứng minh rằng
•(ℱ∗( )) = { ′|∃ ∈ : 〈 , ′〉 ∈ (1 ∪ ∘ )} (theo định nghĩa •và ℱ∗)
= { ′|∃ ∈ : ′ = } ∪ { ′|∃ ∈ : ∃ ′′: 〈 , ′′〉 ∈ ∧ 〈 ′′, ′〉 ∈ }
(theo định nghĩa và hàm hợp ∘ )
= ∪ { ′|∃ ′′ ∈ •( ) ∧ 〈 ′′, ′〉 ∈ } (theo định nghĩa •)
= ℱ•( •( )) (theo định nghĩa ℱ•( ) = ∪ [ ] ) Bằng lý thuyết chuyển đổi điểm cố định suy ra rằng
•( ∗) = •( ∅⊆ℱ∗) = ∅⊆ℱ•
Quan sát thấy rằng, nếu Σ là một tập hữu hạn thì chúng ta có một thuật toán lặp tới được tiến (forward reachability iterative algorithm) khi đó
48
∅⊆ℱ• = ⋃ ℱ• (∅) có thể được sử dụng để kiểm tra tất cả các trạng thái tới được thỏa mãn một đặc tả an toàn S: •( ∗) ⊆ ⟺ ∀ : ℱ• (∅) ⊆ .
Hình 2.26: Trừu tượng hóa đến ngữ nghĩa tới được
Trong hình 2.26 mô tả các biểu diễn của ngữ nghĩa thông qua quá trình từ tượng hóa lẫn nhau, bắt đầu từ hệ chuyên dịch, đến ngữ nghĩa vết và cuối cùng là ngữ nghĩa tới được [7].
2.8. Kết luận chương 2
Trong chương này, tôi đã trình bày các khái niệm cơ bản về kỹ thuật giải thích trừu tượng, cơ sở toán học của kỹ thuật giải thích trừu tượng: lý thuyết dàn, lý thuyết điểm cố định, biểu diễn ngữ nghĩa chương trình trên một dàn, kết nối Galois, ….
Các phương pháp biểu diễn ngữ nghĩa chương trình dưới dạng quan hệ chuyển tiếp, hệ chuyển dịch, trừu tượng hóa ngữ nghĩa chương trình, biểu diễn ngữ nghĩa vết dưới dạng điểm cố định, trừu tượng hóa ngữ nghĩa vết bằng bao đóng phản xạ bắc cầu, …, các ngữ nghĩa được trừu tượng hóa lẫn nhau để tối ưu hóa phân tích chương trình tĩnh sẽ được ứng dung trong chương 3.
49
Chương 3 - THỰC NGHIỆM 3.1. Giới thiệu về TVLA
TVLA (3 – Valued Logic Analysis Engine) là một công cụ mã nguồn mở được xây dựng và làm việc trên môi trường Java, được phát triển bởi Lev- Ami Đại học Khoa học Máy tính Tel Aviv (School of Computer Science Tel Aviv University), thành phố Tel Aviv - Israel, nhằm phục vụ mục tiêu nghiên cứu, phát triển lý thuyết giải thích trừu tượng. Là một công cụ mạnh cho việc trừu tượng hóa các đối tượng. Nó cho phép tự động tạo ra sự mô tả trừu tượng từ các ngữ nghĩa, đối tượng cụ thể, cung cấp chế độ kiểm tra thuộc tính liên quan đến heap của chương trình, TVLA có giao diện làm việc là dòng lệnh.
TVLA có các tính năng sau:
Hỗ trợ ngôn ngữ đặc tả để biểu diễn ngữ nghĩa cụ thể của một chương trình;
Tự động sinh biểu diễn trừu tượng của ngữ nghĩa cụ thể;
Có thể điều chỉnh các kết quả trừu tượng và quá trình biến đổi trừu tượng.
Cấu trúc thực hiện lệnh TVLA như sau:
tvla <là tên của chương trình> [tệp dữ liệu vào] [các lựa chọn] Trong đó các lựa chọn gồm có:
- d : Bật chế độ gỡ lỗi.
- action [f][c]pu[c]b: Xác định chế độ ưu tiên khi thực hiện các toán tử. Mặc định fpucb.
f - Focus, c - Coerce, p - Precondition. u - Update, b - Blur.
- join [algorithm]: Định kiểu liên kết các phương thức áp dụng. rel - Kết hợp các liên hệ.
part - Kết hợp một phần.
50 - ms <number>: Giới hạn cấu trúc. - mm <number>: Giới hạn thông báo.
- save {back|ext|all}: Xác định thời gian lưu cấu trúc bộ nhớ. back - Mỗi khi quay lại đỉnh đã xét (mặc định).
ext - Mỗi khi bắt đầu xử lý đối tượng khác. all - Tại mỗi vị trí của chương trình.
- noautomatic: Không tự động phát sinh các ràng buộc. - props <file name>: Có thể sử dụng đặc tả thuộc tính tệp. - log <file name>: Ghi các bước thực hiện ra tệp.
- tvs <file name>: Tạo tệp kết quả đầu ra định dạng TVS. - xml <file name>: Tạo tệp kết quả định dạng XML của CFG
- tr:tvs <file name>: Tạo tệp đầu ra quan hệ chuyển tiếp định dạng TVS - dot <file name>: Tạo tệp kết quả định dạng DOT.
- tr:dot <file name>: Tạo tệp đầu ra quan hệ chuyển tiếp định dạng DOT. - D<macro name>[(value)]: Thiết lập một Macro tiền xử lý bằng C. - nowarnings: Bỏ qua tất cả các cảnh báo.
- path <directory path>: Đường dẫn để thực hiện chương trình. - post: Đánh giá hành động.
3.2. Phân tích trong TVLA
Kỹ thuật giải thích trừu tượng trong phân tích tĩnh cho phép tóm tắt hành vi (ngữ nghĩa cụ thể) của lệnh trong chương trình trên tập vô hạn các trạng thái có thể của bộ nhớ.
Kết quả sau tóm tắt được gọi là ngữ nghĩa trừu tượng của lệnh đó. Ngữ nghĩa cụ thể của một lệnh trong chương trình thường được biểu diễn thông qua các phương pháp hình thức và được sử dụng khá tự nhiên.
Tuy nhiên, trừu tượng hóa ngữ nghĩa cụ thể để tạo ra ngữ nghĩa trừu tượng đảm bảo tính mạnh, chính xác và có khả năng lập luận được lại là một vấn đề khó khăn. Điều này đặc biệt đúng với một số vấn đề trong thực tế như:
51
phân tích hình dạng (Shape Analysis), phân tích con trỏ, trong đó ngữ nghĩa cụ thể liên quan trực tiếp tới cấu trúc dữ liệu và bộ nhớ.
Trong các kỹ thuật phân tích hình dạng thì phân tích hình dạng dựa trên 3-valued logic (Parametric Shape analysis via 3-valued logic) cho đến nay vẫn là phương pháp chính để phân tích heap của chương trình.
Kỹ thuật này được giới thiệu bởi Sagiv [1]. Sau đó Lev-Ami cài đặt các ý tưởng trong phương pháp này và tạo ra công cụ TVLA [13]. TVLA bắt đầu với ngữ nghĩa cụ thể (ngữ nghĩa thực thi - Operationl semantics) của một chương trình. Ngữ nghĩa thực thi được đặc tả bằng logic vị từ cấp một với bao đóng bắc cầu.
Một đầu vào nữa của TVLA là biểu diễn trừu tượng của tất cả các trạng thái bộ nhớ ở điểm vào của chương trình cần phân tích. TVLA sẽ tự động sinh ra ngữ nghĩa trừu tượng, và với mỗi điểm chương trình (program point) sinh ra một giải thích trừu tượng của các trạng thái bộ nhớ ở điểm đó.
TVLA được cài đặt bằng Java và đã sử dụng thành công trong việc phân tích hình dạng của các chương trình thao tác với các danh sách liên kết (danh sách liên kết đơn, danh sách liên kết kép, ..), để chứng minh tính an toàn của hệ thống Mobile Ambients, và xác minh tính đúng đắn cục bộ của một số chương trình sắp xếp (thao tác trên danh sách liên kết).
3.2.1. Cấu trúc 3-valued Logic
Cấu trúc 3-valued logic của Kleene được mở rộng từ 2-valued logic thông thường bởi việc đưa thêm giá trị đặc biệt ½ (giá trị chưa xác định). Các toán tử mệnh đề được Kleene thể hiện trong Hình 3.1.
Giá trị 0 và 1 được gọi là các giá trị xác định, giá trị 1/2 được gọi là giá trị chưa xác định và định nghĩa một quan hệ thứ tự từng phần ⊑ về giá trị
chân lý để phản ánh thông tin: l1 ⊑ l2 thể hiện rằng l1 có nhiều thông tin xác
52
Hình 3.1: Các toán tử 3-valued logic của Kleene
Định nghĩa 3.1: Cho l1, l2 ∈ {0, 1/2, 1}, ta định nghĩa thứ tự thông
tin trên tập giá trị chân lý như sau: l1 ⊑ l2 nếu l1 = l2 hoặc l2 = 1/2. Kí
hiệu ⊔ (join) biểu diễn cận trên nhỏ nhất theo quan hệ ⊑, tức là l1 ⊔ l2 = l1 nếu l1 = l2 và l2=1/2 nếu ngược lại. Ngữ nghĩa của Kleene về 3-valued logic
là đơn điệu theo quan hệ thứ tự trên [13].
3.2.2. Biểu diễn trạng thái bộ nhớ Heap qua cấu trúc Logic
Một cấu trúc 2-valued logic S là một bộ ( , ) trong đó là tập các phần tử (bao gồm các biến và hằng), các phần tử ở đây chính là các nút trên đồ thị Heap (tập các khối bộ nhớ được cấp phát), là tập các vị từ trên
(biểu diễn quan hệ tham chiếu trong Heap). Một vị từ p trên S được kí hiệu là . Với mỗi vị từ p có số chiều k, là hàm: : ( ) ⟶ {0, 1}.
Một heap cụ thể của chương trình được mô tả bằng cấu trúc 2-valued logic: là tập các nút trên đồ thị heap, tức là tập các khối bộ nhớ được cấp phát. Các vị từ biểu diễn quan hệ tham chiếu trong heap. [13]
Vị từ đơn nguyên có thể biểu diễn quan hệ tham chiếu giữa một biến
chương trình với một nút của heap: Nếu biến x tham chiếu tới nút n1, chúng ta tạo một vị từ đơn nguyên x mà x(n1) = 1. Vị từ nhị nguyên được dùng để